我试图在我的代码中使用Reflection1示例实现数据转换。
GetSourceValue函数有一个比较各种类型的开关,但我想删除这些类型和属性,并让GetSourceValue只使用一个字符串作为参数来获取属性的值。我想在字符串中传递一个类和属性,并解析属性的值。
这可能吗?
1原始博客文章的Web存档版本
我试图在我的代码中使用Reflection1示例实现数据转换。
GetSourceValue函数有一个比较各种类型的开关,但我想删除这些类型和属性,并让GetSourceValue只使用一个字符串作为参数来获取属性的值。我想在字符串中传递一个类和属性,并解析属性的值。
这可能吗?
1原始博客文章的Web存档版本
当前回答
public static object GetPropValue(object src, string propName)
{
return src.GetType().GetProperty(propName).GetValue(src, null);
}
当然,您会想要添加验证和诸如此类的东西,但这就是它的要点。
其他回答
使用系统的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;
}
它可以很好地获取对象的Location属性
Label1.Text = GetObjProperty(button1, "Location").ToString();
我们将得到Location: {X=71,Y=27} 我们还可以返回位置。X或位置。Y也一样。
public static object GetPropValue(object src, string propName)
{
return src.GetType().GetProperty(propName).GetValue(src, null);
}
当然,您会想要添加验证和诸如此类的东西,但这就是它的要点。
当你想要遍历对象中的所有属性,然后使用属性的每个值时,必须使用这段代码:
foreach (var property in request.GetType().GetProperties())
{
var valueOfProperty = property.GetValue(properties, null);
}
这是我的解决方案。它也适用于COM对象,并允许从COM对象访问集合/数组项。
public static object GetPropValue(this object obj, string name)
{
foreach (string part in name.Split('.'))
{
if (obj == null) { return null; }
Type type = obj.GetType();
if (type.Name == "__ComObject")
{
if (part.Contains('['))
{
string partWithoundIndex = part;
int index = ParseIndexFromPropertyName(ref partWithoundIndex);
obj = Versioned.CallByName(obj, partWithoundIndex, CallType.Get, index);
}
else
{
obj = Versioned.CallByName(obj, part, CallType.Get);
}
}
else
{
PropertyInfo info = type.GetProperty(part);
if (info == null) { return null; }
obj = info.GetValue(obj, null);
}
}
return obj;
}
private static int ParseIndexFromPropertyName(ref string name)
{
int index = -1;
int s = name.IndexOf('[') + 1;
int e = name.IndexOf(']');
if (e < s)
{
throw new ArgumentException();
}
string tmp = name.Substring(s, e - s);
index = Convert.ToInt32(tmp);
name = name.Substring(0, s - 1);
return index;
}
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;
}