2011-10-13 5 views
2

私は、式ツリーを使用して、コレクションの各値に述語を適用します(read mapまたはlist.All(述語))。述語に入力パラメータを渡しても、Allによって供給された値にバインドされていないように見えますが、ちょっと残念です。ここではこれが(私はしばらく見て)別の質問に答えた場合、私は::C#式ツリーバインディング

public class SomeType 
{ 
    public IEnumerable<bool> Collection { get; set; } 
} 

void Main() 
{ 
    var list = new SomeType { 
    Collection = new List<bool> { true, true, true } 
    }; 
    var functor = Compiler((SomeType t) => t.Collection, (bool x) => x); 
    functor(list).Dump(); 
} 

MethodInfo FindMethod<TInput>(Type location, string name) 
{ 
    var handle = location 
     .GetMethods(BindingFlags.Static | BindingFlags.Public) 
     .Where(method => method.Name == name).First(); 

    return handle.MakeGenericMethod(typeof(TInput)); 
} 

Predicate<TObject> Compiler<TObject, TProperty>(
    Expression<Func<TObject, IEnumerable<TProperty>>> selector, 
    Expression<Predicate<TProperty>> predicate) 
{ 
    var query = FindMethod<TProperty>(typeof(Enumerable), "All"); 
    var expression = Expression.Call(query, 
     new Expression[] { 
      Expression.Invoke(selector, selector.Parameters), 
      Expression.Lambda<Func<TProperty, bool>>(predicate.Body, 
         Expression.Parameter(typeof(TProperty))), 
     });   

    return Expression.Lambda<Predicate<TObject>>(expression, 
     selector.Parameters).Compile(); 
} 

おかげで、申し訳ありませんで働いています(linqpadを使用して)コードがあります。

答えて

1

これは機能しますが、Predicate<TObject>Func<TObject, bool>に変更する必要がありました。あなたが望むなら、私はそれを元に戻すことができます。

static Predicate<TObject> Compiler<TObject, TProperty>(
    Expression<Func<TObject, IEnumerable<TProperty>>> selector, 
    Expression<Func<TProperty, bool>> predicate) 
{ 
    var query = FindMethod<TProperty>(typeof(Enumerable), "All"); 
    var expression = Expression.Call(
     query, 
     Expression.Invoke(selector, selector.Parameters), 
     predicate); 

    return Expression 
     .Lambda<Predicate<TObject>>(expression, selector.Parameters) 
     .Compile(); 
} 

5分後に...そして、あなたは本当にPredicate<TObject>を使用したい場合は...

static Predicate<TObject> Compiler<TObject, TProperty>(
    Expression<Func<TObject, IEnumerable<TProperty>>> selector, 
    Expression<Predicate<TProperty>> predicate) 
{ 
    var query = FindMethod<TProperty>(typeof(Enumerable), "All"); 

    var predicateAsFunc = Expression.Lambda<Func<TProperty, bool>>(
     predicate.Body, 
     predicate.Parameters); 

    var expression = Expression.Call(
     query, 
     Expression.Invoke(selector, selector.Parameters), 
     predicateAsFunc); 

    return Expression 
     .Lambda<Predicate<TObject>>(expression, selector.Parameters) 
     .Compile(); 
} 
+0

私はちょうど述語パラメーター(ため息)を通過しなかった理由を見当もつかない。ああ、私は述語をコードの残りの部分に結びつけているので、述語を使用しなければなりません。ありがとう! – Bashwork

+0

@Bashworkもし私が少し短くする必要があれば。今度は、 'select.Parameters'(1つ少ない行) – xanatos