我试图在我的代码中使用Reflection1示例实现数据转换。
GetSourceValue函数有一个比较各种类型的开关,但我想删除这些类型和属性,并让GetSourceValue只使用一个字符串作为参数来获取属性的值。我想在字符串中传递一个类和属性,并解析属性的值。
这可能吗?
1原始博客文章的Web存档版本
我试图在我的代码中使用Reflection1示例实现数据转换。
GetSourceValue函数有一个比较各种类型的开关,但我想删除这些类型和属性,并让GetSourceValue只使用一个字符串作为参数来获取属性的值。我想在字符串中传递一个类和属性,并解析属性的值。
这可能吗?
1原始博客文章的Web存档版本
当前回答
jheddings和AlexD都写了关于如何解析属性字符串的出色答案。我想把我的库也加入其中,因为我专门为此编写了一个库。
路径。CSharp的主类是Resolver。默认情况下,它可以解析属性、数组和字典条目。
举个例子,如果你有一个这样的物体
var o = new { Property1 = new { Property2 = "value" } };
想要获得Property2,你可以这样做:
IResolver resolver = new Resolver();
var path = "Property1.Property2";
object result = r.Resolve(o, path);
//=> "value"
这是它可以解析的路径的最基本示例。如果你想看看它还能做什么,或者你可以如何扩展它,只需前往它的Github页面。
其他回答
public static object GetPropValue(object src, string propName)
{
return src.GetType().GetProperty(propName).GetValue(src, null);
}
当然,您会想要添加验证和诸如此类的东西,但这就是它的要点。
看看Heleonix。反映图书馆。你可以通过路径获取/设置/调用成员,或者创建一个getter/setter (lambda编译成委托),这比反射更快。例如:
var success = Reflector.Get(DateTime.Now, null, "Date.Year", out int value);
或者只创建一个getter并缓存以供重用(这样性能更好,但如果中间成员为空可能会抛出NullReferenceException):
var getter = Reflector.CreateGetter<DateTime, int>("Date.Year", typeof(DateTime));
getter(DateTime.Now);
或者如果你想创建一个List<Action<object, object>>的不同getter,只需要为已编译的委托指定基本类型(类型转换将被添加到已编译的lambdas中):
var getter = Reflector.CreateGetter<object, object>("Date.Year", typeof(DateTime));
getter(DateTime.Now);
捷径....
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());
下面的方法非常适合我:
class MyClass {
public string prop1 { set; get; }
public object this[string propertyName]
{
get { return this.GetType().GetProperty(propertyName).GetValue(this, null); }
set { this.GetType().GetProperty(propertyName).SetValue(this, value, null); }
}
}
获取属性值:
MyClass t1 = new MyClass();
...
string value = t1["prop1"].ToString();
设置属性值。
t1["prop1"] = value;
这是我的解决方案。它也适用于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;
}