在运行时已知类型的表达式Lambda

4

我正在尝试创建一些表达式,其中我将使用lambda创建两种方法:选择器和条件。简化后的用法是condition(selector(data)),但中间类型只在运行时才知道。我有以下代码,只要中间类型是对象,就可以工作,但在运行时我知道真实类型并希望使用它。

    public static ICondition<TData> GetRelayConditionByReflection(string name, string message, string assemblyName,
        string fullyQualifiedName, string conditionMethodName, string selectorMethodName) {
        var asm = Assembly.LoadFrom(assemblyName);
        var type = asm.GetType(fullyQualifiedName);
        var selectorMi = type.GetMethod(selectorMethodName, BindingFlags.Static | BindingFlags.Public);
        var conditionMi = type.GetMethod(conditionMethodName, BindingFlags.Static | BindingFlags.Public);

        var tCondType = selectorMi.ReturnType;
        var returnType = typeof(RelayCondition<,>);
        var typeArgs = new[] { typeof(TData), tCondType };



        var paramTData = Expression.Parameter(typeof(TData), "data");
        var selector = Expression.Lambda<Func<TData, object>>(
            Expression.Call(selectorMi, paramTData), paramTData).Compile();

        var paramTCondition = Expression.Parameter(tCondType, "condition");

        var condition = Expression.Lambda<Func<object, bool>>(
            Expression.Call(conditionMi, paramTCondition), paramTCondition).Compile();



        return (ICondition<TData>)Activator.CreateInstance(returnType.MakeGenericType(typeArgs), name, condition, message, selector);
    }

具体来说,有Expression.Lambda<Func<TData, object>>Expression.Lambda<Func<object, bool>>,其中object目前只允许中间类型为object。
是否可能在仅在运行时已知类型的情况下创建此内容?我对整个问题开放其他方法,只要性能不差即可。

你为什么关心中间类型是什么? - Servy
我不想这样做,但如果我使用对象,那么两种方法都必须在它们的定义中使用对象,而我想避免这种情况。 - hvidgaard
1个回答

3

如果你不需要隐式的下转换(例如声明一个Func<object>,而实际上你的方法返回的是Func<Foo>),那么你可以使用非泛型的Expression.Lambda()方法。它返回一个LambdaExpression,但实际上它返回一个下转型为LambdaExpressionFunc<>ActionExpression<>Expression<>LambdaExpression的子类),所以:

var condition = Expression.Lambda(
        Expression.Call(conditionMi, paramTCondition), paramTCondition).Compile();

现在condition是一个Delegate,但实际上它是一个Func<>(如果有返回类型void则为Action)。


这个可以工作,并且在运行时确定委托是否为适当的类型,如果不是则抛出异常。类型得到保留,在出现错误时仍然能够快速失败。谢谢。 - hvidgaard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接