我有一些代码,当前使用反射来调用类的方法,类和方法名称为字符串。每个类的所有方法都有相同的签名 - 取字符串,字符串,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函数上遇到错误,说&#39;为lambda声明提供的参数数量不正确&#39;。我在这里缺少什么?
答案 0 :(得分:2)
您需要提供所有外部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);