C# 使用Expression代替反射获取动态类中的值

发布时间 2023-06-13 12:07:04作者: 糯米白白

示例代码:

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