【问题标题】:Convert Expression<Func<T, U>> to Expression<Func<object, object>>将 Expression<Func<T, U>> 转换为 Expression<Func<object, object>>
【发布时间】:2017-04-13 08:30:04
【问题描述】:

我有一个LambdaExpression,它的类型是Expression&lt;Func&lt;T, string&gt;&gt;。目前的代码设计不允许我保留T,这意味着我不得不使用较慢的DynamicInvoke 而不是Invoke

由于我知道T 的类型,我想转换表达式,使其接受T 对象,从而允许我使用Invoke。怎么样?

这是一个好的开始

class Program
{
    class MyClass
    {
        public string MyProperty => "Foo";
    }

    static LambdaExpression GetExpression(Expression<Func<MyClass, object>> expr)
    {
        return expr;
    }

    static void Main(string[] args)
    {
        var e1 = GetExpression(t => t.MyProperty);
        var e2 = Expression.Lambda<Func<object, object>>(e1, e1.Parameters);

        object myClass = new MyClass();
        string s1 = (string)e1.Compile().DynamicInvoke(myClass);
        object s2 = e2.Compile().Invoke(myClass);
    }
}

【问题讨论】:

  • 您的问题与您的标题不符。您是要将Func&lt;T, U&gt; 转换为Func&lt;object, object&gt;,将Func&lt;T, object&gt; 转换为Func&lt;object, object&gt;,还是将Expression&lt;Func&lt;T, object&gt;&gt; 转换为Expression&lt;Func&lt;object, object&gt;&gt;?这三个人都有不同的答案。
  • 我可以编写一些代码来解决这个问题...只是一个问题...您想将这些表达式用于 Entity Framework/LINQ to SQL 还是简单地编译这些表达式?因为将Expressions 更改为Func&lt;object, object&gt; 可能会使它们与EF 不兼容。
  • 更新了问题。最后,我想编译表达式以用作类型化委托,这样我就可以使用 Invoke() 而不是 DynamicInvoke()。我相信在某种程度上需要Expression.Convert

标签: c# lambda expression-trees


【解决方案1】:

非表达式版本看起来像

Func<object, object> Convert<T>(Func<T, object> f) {
  return o => f((T)o);
}

这也是你在表达式版本中需要做的。没错,Expression.Convert 可以做到。

Expression<Func<MyClass, object>> e1 = t => t.MyProperty;
var p = Expression.Parameter(typeof(object));
var e2 = Expression.Lambda<Func<object, object>>(
    Expression.Invoke(e1, Expression.Convert(p, typeof(MyClass))), p);

注意:正如@xanatos 正确指出的那样,用于转换例如Expression&lt;Func&lt;T, int&gt;&gt;Expression&lt;Func&lt;object, object&gt;&gt;,虽然 C# 支持从 intobject 的隐式装箱转换,但表达式树不支持。如果这与问题相关,则需要另一个 Expression.Convert

【讨论】:

  • 拯救了我的一天。谢谢!
  • @xanatos 对于Expression&lt;Func&lt;T, U&gt;&gt;Expression&lt;Func&lt;object, object&gt;&gt;,这确实是必要的对于Expression&lt;Func&lt;T, object&gt;&gt;Expression&lt;Func&lt;object, object&gt;&gt;,它不是。我认为Expression&lt;Func&lt;T, U&gt;&gt; 已被编辑掉并且与问题无关,但我现在看到它还没有被编辑掉。你可能是对的。
  • @hvd 正是我的想法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多