将 Expression<Func<T, U>> 转换为 Expression<Func<object, object>>。

3
我有一个 LambdaExpression 的类型是 Expression<Func<T, string>>。目前代码的设计不允许我保留 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);
    }
}

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

5
非表达式版本将如下所示:
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<Func<T, int>>转换为Expression<Func<object, object>>,尽管C#支持从intobject的隐式装箱转换,但表达式树不支持。如果这与问题有关,则需要使用另一个Expression.Convert


救了我的一天。谢谢! - l33t
@hvd 我会在 Expression.Invoke 外部添加另一个 Expression.Convert 到对象,以防你有一个值类型(它们不是隐式装箱的)。 - xanatos
@xanatos 对于将 Expression<Func<T, U>> 转换为 Expression<Func<object, object>>,这确实是必要的。但对于将 Expression<Func<T, object>> 转换为 Expression<Func<object, object>>,则不需要。我原以为 Expression<Func<T, U>> 已被编辑掉并与问题无关,但现在看来它还没有被编辑掉。你可能是正确的。 - user743382
@hvd 恰好是我的想法。 - xanatos

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