2017-04-13 120 views
1

我有一个LambdaExpression,它是Expression<Func<T, string>>类型。代码的设计目前不允许我继续T这意味着我不得不使用较慢的DynamicInvoke,而不是Invoke将表达式<Func<T, U>>转换为表达式<Func <object,object >>

因为我知道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); 
    } 
} 
+0

你的问题不符合您的标题。您是否想要转换'Func键'来'Func键<对象,对象>'转换'Func键'来'Func键<对象,对象>',或转换'表达>'来'表达'?这三个人都有不同的答案。 – hvd

+0

我可以编写一些代码来解决这个问题...只有一个问题...你想使用这些表达式实体框架/ LINQ to SQL,或者你想简单地编译这些表达式吗?因为改变'Expression'使它们成为'Func '可能会使它们与EF不兼容。 – xanatos

+0

更新了问题。最后,我想编译表达式以用作类型化委托,以便我可以使用Invoke()而不是DynamicInvoke()。我相信'Expression.Convert'是需要某种方式。 – l33t

回答

3

非表达版本会是什么样

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

+0

保存了我的一天。谢谢! – l33t

+0

@hvd我将再增加'Expression.Convert'从外部对象到'Expression.Invoke',在你有一个价值型的情况下(他们是不会隐盒装) – xanatos

+0

@xanatos对于'表达>''到表达>',这确实可能有必要对于'表达>''来表达>',事实并非如此。我认为'Expression >'已经被编辑出来,并且与这个问题无关,但我现在看到它没有被编辑出来。也许你是对的。 – hvd

相关问题