在 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 GetSourceValuefunction has a switch comparing various types, but I want to remove these types and properties and have GetSourceValueget 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. nullmeans 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 CallByNameof the Microsoft.VisualBasicnamespace (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);
}

