表达式树的问题 - 如何将实例方法转换为 Func



我有一些代码,目前使用反射来调用类上的方法,类和方法名称作为字符串。每个类上的所有方法都将具有相同的签名 - 获取字符串,字符串,IDictionary和返回bool。

我试图做的是用一个表达式构建它,并基本上将 Func 缓存在字典中,所以反射只在第一次调用它时完成。但是我对如何做到这一点有点困惑 - 我目前有以下代码

public Func<string, string, IDictionary<string, string>, bool> GetFunc(string className, string methodName)
{
    lock (_locker)
    {
        if (!_criteriaCache.ContainsKey(className) || !_criteriaCache[className].ContainsKey(methodName))
        {
            object o = Assembly.GetExecutingAssembly().CreateInstance(className);
            var instance = Expression.Parameter(o.GetType(), "instance");
            var value = Expression.Parameter(typeof (string), "value");
            var compareValue = Expression.Parameter(typeof(string), "compareValue");
            var parameters = Expression.Parameter(typeof(IDictionary<string,string>), "parameters");
            var method = o.GetType().GetMethod(methodName,
                System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
            Func<string, string, IDictionary<string, string>, bool> result =
                Expression.Lambda<Func<string, string, IDictionary<string, string>, bool>>(
                    Expression.Call(instance,method,new List<Expression> { value,compareValue,parameters })).Compile();
            if (!_criteriaCache.ContainsKey(className))
                _criteriaCache.Add(className,new Dictionary<string, Func<string, string, IDictionary<string, string>, bool>>());
            _criteriaCache[className].Add(methodName,result);
        }
    }
    return _criteriaCache[className][methodName];
}

但是,我在 Expression.Call 函数上收到一个错误,说"为 lambda 声明提供的参数数量不正确"。我在这里错过了什么?

您需要

提供所有外部ParameterExpression声明作为Expression.Lambda的最终参数。目前你还没有给它。但是 - 目前还不清楚您希望对instance做什么,因为您的 lambda 不需要实例。您可能打算instance Expression.Constant(o)

var instance = Expression.Constant(o);
...
var result =
    Expression.Lambda<Func<string, string, IDictionary<string, string>, bool>>(
        Expression.Call(instance, method, new List<Expression> {
            value, compareValue, parameters }),
        value, compareValue, parameters).Compile();

不过,看起来您正在对参数进行直接传递 - 在这种情况下,这可能更简单:

var result = (Func<string, string, IDictionary<string, string>, bool>)
      Delegate.CreateDelegate(
          typeof(Func<string, string, IDictionary<string, string>, bool>),
          o, method);

最新更新