在 C# 中使用反射从字符串中获取属性值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1196991/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get property value from string using reflection in C#
提问by pedrofernandes
I am trying implement the Data transformation using Reflection1example in my code.
我正在尝试在我的代码中使用 Reflection 1示例实现数据转换。
The GetSourceValue
function has a switch comparing various types, but I want to remove these types and properties and have GetSourceValue
get the value of the property using only a single string as the parameter. I want to pass a class and property in the string and resolve the value of the property.
该GetSourceValue
函数有一个比较各种类型的开关,但我想删除这些类型和属性,并GetSourceValue
仅使用单个字符串作为参数来获取属性的值。我想在字符串中传递一个类和属性并解析该属性的值。
Is this possible?
这可能吗?
采纳答案by Ed S.
public static object GetPropValue(object src, string propName)
{
return src.GetType().GetProperty(propName).GetValue(src, null);
}
Of course, you will want to add validation and whatnot, but that is the gist of it.
当然,您会想要添加验证和诸如此类的东西,但这就是它的要点。
回答by jheddings
How about something like this:
这样的事情怎么样:
public static Object GetPropValue(this Object obj, String name) {
foreach (String part in name.Split('.')) {
if (obj == null) { return null; }
Type type = obj.GetType();
PropertyInfo info = type.GetProperty(part);
if (info == null) { return null; }
obj = info.GetValue(obj, null);
}
return obj;
}
public static T GetPropValue<T>(this Object obj, String name) {
Object retval = GetPropValue(obj, name);
if (retval == null) { return default(T); }
// throws InvalidCastException if types are incompatible
return (T) retval;
}
This will allow you to descend into properties using a single string, like this:
这将允许您使用单个字符串下降到属性,如下所示:
DateTime now = DateTime.Now;
int min = GetPropValue<int>(now, "TimeOfDay.Minutes");
int hrs = now.GetPropValue<int>("TimeOfDay.Hours");
You can either use these methods as static methods or extensions.
您可以将这些方法用作静态方法或扩展。
回答by Guvante
You never mention what object you are inspecting, and since you are rejecting ones that reference a given object, I will assume you mean a static one.
您从未提及您正在检查的对象,并且由于您拒绝引用给定对象的对象,因此我假设您指的是静态对象。
using System.Reflection;
public object GetPropValue(string prop)
{
int splitPoint = prop.LastIndexOf('.');
Type type = Assembly.GetEntryAssembly().GetType(prop.Substring(0, splitPoint));
object obj = null;
return type.GetProperty(prop.Substring(splitPoint + 1)).GetValue(obj, null);
}
Note that I marked the object that is being inspected with the local variable obj
. null
means static, otherwise set it to what you want. Also note that the GetEntryAssembly()
is one of a few available methods to get the "running" assembly, you may want to play around with it if you are having a hard time loading the type.
请注意,我用局部变量标记了正在检查的对象obj
。null
表示静态,否则将其设置为您想要的。另请注意,这GetEntryAssembly()
是获取“正在运行”程序集的几种可用方法之一,如果您在加载类型时遇到困难,您可能想尝试一下。
回答by Fredou
What about using the CallByName
of the Microsoft.VisualBasic
namespace (Microsoft.VisualBasic.dll
)? It uses reflection to get properties, fields, and methods of normal objects, COM objects, and even dynamic objects.
怎么样使用CallByName
的的Microsoft.VisualBasic
命名空间(Microsoft.VisualBasic.dll
)?它使用反射来获取普通对象、COM 对象甚至动态对象的属性、字段和方法。
using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
and then
进而
Versioned.CallByName(this, "method/function/prop name", CallType.Get).ToString();
回答by Kyle
Dim NewHandle As YourType = CType(Microsoft.VisualBasic.CallByName(ObjectThatContainsYourVariable, "YourVariableName", CallType), YourType)
回答by AlexD
Great answer by jheddings. I would like to improve it allowing referencing of aggregated arrays or collections of objects, so that propertyName could be property1.property2[X].property3:
jheddings 的精彩回答。我想改进它,允许引用聚合数组或对象集合,以便 propertyName 可以是 property1.property2[X].property3:
public static object GetPropertyValue(object srcobj, string propertyName)
{
if (srcobj == null)
return null;
object obj = srcobj;
// Split property name to parts (propertyName could be hierarchical, like obj.subobj.subobj.property
string[] propertyNameParts = propertyName.Split('.');
foreach (string propertyNamePart in propertyNameParts)
{
if (obj == null) return null;
// propertyNamePart could contain reference to specific
// element (by index) inside a collection
if (!propertyNamePart.Contains("["))
{
PropertyInfo pi = obj.GetType().GetProperty(propertyNamePart);
if (pi == null) return null;
obj = pi.GetValue(obj, null);
}
else
{ // propertyNamePart is areference to specific element
// (by index) inside a collection
// like AggregatedCollection[123]
// get collection name and element index
int indexStart = propertyNamePart.IndexOf("[")+1;
string collectionPropertyName = propertyNamePart.Substring(0, indexStart-1);
int collectionElementIndex = Int32.Parse(propertyNamePart.Substring(indexStart, propertyNamePart.Length-indexStart-1));
// get collection object
PropertyInfo pi = obj.GetType().GetProperty(collectionPropertyName);
if (pi == null) return null;
object unknownCollection = pi.GetValue(obj, null);
// try to process the collection as array
if (unknownCollection.GetType().IsArray)
{
object[] collectionAsArray = unknownCollection as object[];
obj = collectionAsArray[collectionElementIndex];
}
else
{
// try to process the collection as IList
System.Collections.IList collectionAsList = unknownCollection as System.Collections.IList;
if (collectionAsList != null)
{
obj = collectionAsList[collectionElementIndex];
}
else
{
// ??? Unsupported collection type
}
}
}
}
return obj;
}
回答by A Ghazal
Using PropertyInfo of the System.Reflectionnamespace. Reflection compiles just fine no matter what property we try to access. The error will come up during run-time.
使用System.Reflection命名空间的PropertyInfo 。无论我们尝试访问什么属性,反射都可以很好地编译。该错误将在运行时出现。
public static object GetObjProperty(object obj, string property)
{
Type t = obj.GetType();
PropertyInfo p = t.GetProperty("Location");
Point location = (Point)p.GetValue(obj, null);
return location;
}
It works fine to get the Location property of an object
获取对象的 Location 属性效果很好
Label1.Text = GetObjProperty(button1, "Location").ToString();
We'll get the Location : {X=71,Y=27} We can also return location.X or location.Y on the same way.
我们将得到 Location : {X=71,Y=27} 我们也可以用同样的方式返回 location.X 或 location.Y。
回答by Budiantowang
shorter way ....
更短的方式....
var a = new Test { Id = 1 , Name = "A" , date = DateTime.Now};
var b = new Test { Id = 1 , Name = "AXXX", date = DateTime.Now };
var compare = string.Join("",a.GetType().GetProperties().Select(x => x.GetValue(a)).ToArray())==
string.Join("",b.GetType().GetProperties().Select(x => x.GetValue(b)).ToArray());
回答by Eduardo Cuomo
Add to any Class
:
添加到任何Class
:
public class Foo
{
public object this[string propertyName]
{
get { return this.GetType().GetProperty(propertyName).GetValue(this, null); }
set { this.GetType().GetProperty(propertyName).SetValue(this, value, null); }
}
public string Bar { get; set; }
}
Then, you can use as:
然后,您可以用作:
Foo f = new Foo();
// Set
f["Bar"] = "asdf";
// Get
string s = (string)f["Bar"];
回答by Recursor
Here is another way to find a nested property that doesn't require the string to tell you the nesting path. Credit to Ed S. for the single property method.
这是查找不需要字符串告诉您嵌套路径的嵌套属性的另一种方法。归功于 Ed S. 的单一属性方法。
public static T FindNestedPropertyValue<T, N>(N model, string propName) {
T retVal = default(T);
bool found = false;
PropertyInfo[] properties = typeof(N).GetProperties();
foreach (PropertyInfo property in properties) {
var currentProperty = property.GetValue(model, null);
if (!found) {
try {
retVal = GetPropValue<T>(currentProperty, propName);
found = true;
} catch { }
}
}
if (!found) {
throw new Exception("Unable to find property: " + propName);
}
return retVal;
}
public static T GetPropValue<T>(object srcObject, string propName) {
return (T)srcObject.GetType().GetProperty(propName).GetValue(srcObject, null);
}