2011-03-27 20 views
5

मैं इस तरह के हस्ताक्षर के साथ एक विधि क्या करना चाहते हैं:Parameterized Linq अभिव्यक्ति सहायता

Expression<Func<TSource, bool>> CreatePropertyFilter<TSource>(Expression<Func<TSource, string>> selector, string value, TextMatchMode matchMode); 

असल में, यह एक संपत्ति चयनकर्ता लेता है (पूर्व: p = p.Name), एक स्ट्रिंग मान और एक enum मूल्य कि StartsWith हो सकता है , EndsWith, Contains, Exact; पाठ मिलान विकल्पों के लिए।

मैं इस विधि को कैसे कार्यान्वित कर सकता हूं कि LINQ2Entities समझ सकते हैं?

Expression<Func<string, bool>> comparerExpression; 

switch (matchMode) 
{ 
    case TextMatchMode.StartsWith: 
     comparerExpression = p => p.StartsWith(value); 
     break; 
    case TextMatchMode.EndsWith: 
     comparerExpression = p => p.EndsWith(value); 
     break; 
    case TextMatchMode.Contains: 
     comparerExpression = p => p.Contains(value); 
     break; 
    default: 
     comparerExpression = p => p.Equals(value); 
     break; 
} 

var equalityComparerParameter = Expression.Parameter(typeof(IncomingMail), null); 
var equalityComparerExpression = Expression.Invoke(comparerExpression, Expression.Invoke(selector, equalityComparerParameter)); 
var equalityComparerPredicate = Expression.Lambda<Func<IncomingMail, bool>>(equalityComparerExpression, equalityComparerParameter); 

समस्या यह है कि Linq2Entities प्रार्थना भाव का समर्थन नहीं करता है: मैं पहले से ही विधि इस तरह नेस्टेड मंगलाचरण अभिव्यक्ति का उपयोग करते कार्यान्वित किया।

इस पर कोई सलाह?

धन्यवाद!

उत्तर

5

अनिवार्य रूप से, एक चयनकर्ता दिया:

input => input.Member 

आप वर्तमान की तरह एक विधेय अभिव्यक्ति का निर्माण कर रहे हैं: अपने शरीर का उपयोग करके बाहर चयनकर्ता अभिव्यक्ति

input => selector(input).Method(value) 

इसके बजाय, 'विस्तृत' (एक MemberExpression), कुछ बनाने के लिए:

input => input.Member.Method(value) 

यह दिखाई देगा:

private static Expression<Func<TSource, bool>> CreatePropertyFilter<TSource> 
    (Expression<Func<TSource, string>> selector, 
    string value, 
    TextMatchMode matchMode) 
{ 
    // Argument-checking here.  

    var body = selector.Body as MemberExpression; 

    if (body == null) 
     throw new ArgumentException("Not a MemberExpression.");  

    // string.StartsWith/EndsWith etc. depending on the matchMode. 
    var method = typeof(string) 
       .GetMethod(GetMethodName(matchMode), new[] { typeof(string) }); 

    // input.Member.method(value) 
    var compEx = Expression.Call(body, method, Expression.Constant(value)); 

    // We can reuse the parameter of the source. 
    return Expression.Lambda<Func<TSource, bool>>(compEx, selector.Parameters); 
} 

कहाँ अनुवाद विधि है:

// I really don't like this enum. 
// Why not explicitly include Equals as a member? 
private static string GetMethodName(TextMatchMode mode) 
{ 
    switch (mode) 
    { 
     case TextMatchMode.StartsWith: 
      return "StartsWith"; 

     case TextMatchMode.EndsWith: 
       return "EndsWith"; 

     case TextMatchMode.Contains: 
      return "Contains"; 

     default: 
      return "Equals"; 
    }  
} 
+0

धन्यवाद, Ani! वास्तव में जो मैं खोज रहा था और एक आकर्षण की तरह काम किया! मैं लैम्ब्डा अभिव्यक्ति दुनिया में बहुत ताजा हूँ। –

संबंधित मुद्दे