【问题标题】:Expression Lambda with types known at runtime具有在运行时已知的类型的表达式 Lambda
【发布时间】:2015-06-15 14:48:05
【问题描述】:

我正在尝试制作一些表达式,我将在其中使用 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&lt;Func&lt;TData, object&gt;&gt;Expression.Lambda&lt;Func&lt;object, bool&gt;&gt;,其中object目前只允许中间类型为对象。

是否可以使用仅在运行时才知道的类型来创建它?我愿意接受其他方法来解决整个问题,只要性能不差。

【问题讨论】:

  • 为什么要关心中间类型是什么?
  • 我没有,但是如果我使用对象,我两个方法都必须在定义中使用对象,我想避免这种情况。

标签: c# lambda expression-trees


【解决方案1】:

如果您不需要隐式向下转换(例如声明 Func&lt;object&gt; 而实际上您的方法返回 Func&lt;Foo&gt;),您可以使用非泛型 Expression.Lambda() 方法。它返回LambdaExpression,但实际上它返回Func&lt;&gt;Expression&lt;&gt;Action 向下转换为LambdaExpressionExpression&lt;&gt;LambdaExpression 的子类),所以:

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

现在conditionDelegate,但实际上它是Func&lt;&gt;(如果返回类型为void,则为Action)。

【讨论】:

  • 这行得通,它会在运行时确定委托是适当的类型,如果不是则抛出异常。类型是保守的,并且在发生错误时仍然会快速失败。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多