通过表达式的动态属性设置器不起作用

本文关键字:设置 不起作用 属性 动态 表达式 | 更新日期: 2023-09-27 17:50:25

嗨,当我在控制台应用程序中运行它时,我有以下完美的工作代码,但它在实际应用程序中失败,异常"指定的cast无效"。在lambda_method(Closure, Object, Object),有人知道这是根本原因吗?

    public class Base
    {
    }
    public class Test:Base
    {
        public string TestProp { get; set; }
    }
    static void Main(string[] args)
    {
        Base test = new Test();
        var prop=test.GetType().GetProperty("TestProp");
        var method = BuildSetAccessor(prop.SetMethod);
        method(test, "sa");
    }
    static Action<object, object> BuildSetAccessor(MethodInfo method)
    {
        var obj = Expression.Parameter(typeof(object), "o");
        var value = Expression.Parameter(typeof(object));
        Expression<Action<object, object>> expr =
            Expression.Lambda<Action<object, object>>(
                Expression.Call(
                    Expression.Convert(obj, method.DeclaringType),
                    method,
                    Expression.Convert(value, method.GetParameters()[0].ParameterType)),
                obj, value);

        return expr.Compile();
}

通过表达式的动态属性设置器不起作用

这不是目前的答案,但我建议您将代码更改为以下内容:

static Action<TOb, TPar> BuildSetAccessor<TOb, TPar>(MethodInfo method)
{
    var obj = Expression.Parameter(method.DeclaringType, "o");
    var value = Expression.Parameter(method.GetParameters()[0].ParameterType);
    if (method.GetParameters().Length > 1)
        throw new ArgumentException("Method with more than 1 parameters is not supported");
    LambdaExpression expr =
        Expression.Lambda(
            Expression.Call(
                obj,
                method,
                value),
            obj, value);
    var compiled = expr.Compile();
    return new Action<TOb, TPar>((o, p) => compiled.DynamicInvoke(o, p));
}

和用法:

var method = BuildSetAccessor<Base, object>(prop.SetMethod);
method(test, "1");

我认为这种方法比在LINQ查询中转换参数更好,因为生成的异常信息更详细。