我有一些代码,目前使用反射来调用类上的方法,类和方法名称作为字符串。每个类上的所有方法都将具有相同的签名 - 获取字符串,字符串,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);