对于一些花哨的反射东西,我有一个 Func 类型的函数,需要将它传递给一个接受 Func 类型的函数,其中 T 直到运行时才知道。例如:
public bool MyOperation(Func<string,bool> op) {
return _myValues.Any(op);
}
public static bool InvokeOperationMethod(MethodInfo info, object obj,Func<object,bool> opAsObject)
{
info.Invoke(obj, opAsObject);
}
问题是,由于我有一个较弱类型的 lambda,我不能将它作为更强类型的参数传递。所以我尝试制作一个帮助器,它会创建一个函数,将较弱类型的 lambda 转换为较强类型。例如,我可以打电话
var converter = CreateConverter(typeof(string));
Func<object,bool> asObject = o => o.ToString() == "a string"; //Dump example
Func<string,bool> asString = (Func<string,bool>)converter(asObject);
Assert.IsTrue(asInt("a string"));
当然,在实际代码中,直到运行时才知道目标类型,并且实际谓词不是一些琐碎的测试。
这是我的尝试:
/// <summary>
/// Converts a predicate of Func<object,bool> to
/// Func<Type,bool> of the given type.
/// </summary>
/// <param name="destType">Type of the dest.</param>
/// <param name="predicate">The predicate.</param>
/// <returns></returns>
public static TransformPredicate CreateConverter(Type destType)
{
// This essentially creates the following lambda, but uses destType instead of T
// private static Func<Func<object, bool>, Func<T, bool>> Transform<T>()
// {
// return (Func<object,bool> input) => ((T x) => input(x));
// }
var input = Expression.Parameter(typeof(Func<object, bool>), "input");
var x = Expression.Parameter(destType, "x");
var convert = Expression.Convert(x, typeof(object));
var callInputOnX = Expression.Invoke(input, convert);
var body2 = Expression.Lambda(callInputOnX, x);
var body1 = Expression.Lambda(typeof(TransformPredicate),body2, input);
return (TransformPredicate) body1.Compile();
}
public delegate object TransformPredicate(Func<object,bool> weak);
这实际上工作得很好,只是它运行得很慢,因为它在每次调用时都隐式调用 CreateDelegate。因此,我尝试通过添加以下内容自己调用 CreateDelegate:
var destFunc = typeof(Func<,>).MakeGenericType(destType, typeof(bool));
var endType = typeof(Func<,>).MakeGenericType(typeof(Func<object, bool>), destFunc);
return (TransformPredicate)compiled.Method.CreateDelegate(endType);
这会导致错误:
System.NotSupportedException:派生类必须提供和实现。
有什么想法我可以自己调用 CreateDelegate 吗?