2015-09-07 63 views
0

说我有一个List<Expression<Func<SomeModel, object>>>,看起来像这样:如何将嵌套表达式列表拆分为单级表达式列表?

x => x.Property1, 
x => x.Property1.P1ChildProperty1, 
x => x.Property1.P1ChildProperty2, 
x => x.Property2, 
x => x.Property2.P2ChildProperty1, 
x => x.Property2.P2ChildProperty2, 
x => x.Property2.P2ChildProperty3 

有一些方法我可以遍历该列表,并产生一组新的列表,只有去一个层次深,像这样:

列表1:

x => x.Property1, 
x => x.Property2 

列表2:

y => y.P1ChildProperty1, 
y => y.P1ChildProperty2 

列表3:

z => z.P2ChildProperty1, 
z => z.P2ChildProperty2, 
z => z.P2ChildProperty3 
+0

你尝试过什么吗?你能分享你试过的代码吗? – MarcinJuraszek

+0

@MarcinJuraszek我尝试了很多东西,但没有一个接近我需要做的,这就是为什么我在这里问。我认为真正的问题/概念足够清晰,让人们明白我在问什么。 –

回答

1

是的,有一种方法可以做到这一点。但这取决于你的班级结构。

var items = new List<Expression<Func<SomeModel, object>>> 
      { 
       x => x.Property1, 
       x => x.Property1.P1ChildProperty1, 
       x => x.Property1.P1ChildProperty2, 
       x => x.Property2, 
       x => x.Property2.P2ChildProperty1, 
       x => x.Property2.P2ChildProperty2, 
       x => x.Property2.P2ChildProperty3 
      }; 
Func<LambdaExpression, Expression<Func<object, object>>> reBase = 
      x => 
      { 
       var memExpr = (MemberExpression)x.Body; 
       var param = Expression.Parameter(typeof(object), "x"); 
       var typedParam = Expression.Convert(param, memExpr.Member.DeclaringType); 
       var property = Expression.Property(typedParam, memExpr.Member.Name); 
       return Expression.Lambda<Func<object, object>>(property, param); 
      }; 

var groupedItems = (from item in items 
        group item by ((MemberExpression)item.Body).Member.DeclaringType into g 
        select g.Select(x => reBase(x)).ToList()).ToList(); 

之后groupedItems包含分裂的重新基础列表,如你所愿。

问题是它要求声明类型。

  • SomeModelChild1类型的Property1Child2Property2
  • <Child1>:这个如果你声明的类型的具有这种性质只会工作P1ChildProperty1P1ChildProperty2
  • <Child2>P1ChildProperty1P1ChildProperty2P1ChildProperty3

我不确定这将对你有所帮助。也许你应该深入研究表达式树来找到一种方法来拆分你的列表。

请记住,这会将lambda签名从Func<SomeModel, object>更改为Func<object, object>

+0

这非常接近,但并不完全创建我以后的列表。它确实将它们分组,但它不会将它们“重新定位”为一级。 –

+0

Ups - 现在我了解您的请求。抱歉。但它仍然是可能的。您必须通过解析属性路径来动态创建新的表达式并进行递归。我必须考虑它。 –

+0

我看到的唯一问题是你不能使用'Func ',因为'Property1'的返回类型不是'SomeModel'类型。也许你必须更改为'Func ',并且你必须在每个lambda中进行投射,但是在这种情况下,所有lambda都具有相同的签名。 (也许动态会工作,但我不确定它是否可用于表达式树。) –