示例代码:
class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
private object obj = new Person
{
Id = 123,
Name = "fred"
};
项目中的Class都是动态生成的,只好用object来存储。
一般常规的方法是用反射去获取对应属性的值,由于速度比较慢,所以使用了Expression去实现。
因为object是动态的类,要取的值也是动态的。所以这里用泛型。
代码如下:
public VT GetValueExpr<T, VT>(T t, string filedName)
{
var type = t.GetType();
var paramExpr = Expression.Parameter(type, "x");
var expr = Expression.Property(paramExpr, filedName);
var funcCompiled = Expression.Lambda<Func<T, VT>>(expr, paramExpr).Compile();
var value = funcCompiled.Invoke(t);
return value;
}
不出意外,代码会报错:
System.ArgumentException: ParameterExpression of type 'ExprDemo.Demo+Person' cannot be used for delegate parameter of type 'System.Object'
这个问题在StackOverflow提问并得到解决了 https://stackoverflow.com/questions/65681824/c-sharp-use-expression-to-get-value-from-an-object
用这段代码就可以了:
public VT GetValueExpr<T, VT>(T t, string filedName)
{
var type = t.GetType();
var paramExpr = Expression.Parameter(typeof(T), "x");
var expr = Expression.Property(Expression.Convert(paramExpr, type), filedName);
var funcCompiled = Expression.Lambda<Func<T, VT>>(expr, paramExpr).Compile();
var value = funcCompiled.Invoke(t);
return value;
}
如果想在此基础上做一些条件判断,可以写成这样:
public bool GetValueExpr<T, VT>(T t, string filedName, Func<VT, bool> func)
{
var type = t.GetType();
var paramExpr = Expression.Parameter(typeof(T), "x");
var expr = Expression.Property(Expression.Convert(paramExpr, type), filedName);
var funcCompiled = Expression.Lambda<Func<T, VT>>(expr, paramExpr).Compile();
var value = funcCompiled.Invoke(t);
return func.Invoke(value);
}
原文链接:https://blog.csdn.net/qq_39930578/article/details/112907837