2010-02-19 16 views
9

ठीक है, मेरा अनुमान है कि यह पहले से ही उत्तर दिया गया है, और मैं अभी तक समझने के लिए वाक्यविन्यास के साथ पर्याप्त परिचित नहीं हूं, इसलिए मेरे साथ सहन करें।गतिशील रूप से लिंक लैम्ब्डा अभिव्यक्ति बनाएं

मेरे वेब ऐप के उपयोगकर्ताओं को एक gridview में आइटम्स की एक लंबी सूची फ़िल्टर करने की आवश्यकता है, जो linqdatasource के माध्यम से उपयोग किया जाता है। मैं वस्तुओं को फ़िल्टर करने के लिए ऑनसेलेक्टिंग इवेंट का उपयोग कर रहा हूं। मैं ड्रॉपडाउनलिस्ट में उपयोगकर्ताओं द्वारा किए गए चयनों के आधार पर उन वस्तुओं को फ़िल्टर करना चाहता हूं।

उदाहरण के लिए, वे चयन "शीर्षक" "इसमें शामिल है" "फ्रेड" यह

e.Result = dbContext.Opps.Where(opp => !opp.Description.Contains("Alpha")); 
में में

e.Result = dbContext.Opps.Where(opp => opp.Title.Contains("Fred")); 

या "विवरण" "शामिल नहीं है" "अल्फ़ा" परिणाम परिणाम

मैं उस अभिव्यक्ति (System.Linq.Expressions.Expression>) को गतिशील रूप से बनाना चाहता हूं, नेस्टेड स्विच अभिव्यक्तियों को उत्पन्न करने के बजाय, क्योंकि ऐसे कई फ़ील्ड हैं जिन्हें मैं जांचना चाहता हूं, और मैं भी इसका उपयोग करना चाहता हूं जांच के साथ शुरू होता है और समाप्त होता है रों। मैं एक स्ट्रिंग के रूप अभिव्यक्ति, इसलिए की तरह बना सकते हैं:

string stringExpression = string.Format("opp => opp.{0}.{1}(\"{2}\")", 
    ddlCustomFilter.SelectedValue, 
    ddlFilterType.SelectedValue, 
    txtFilterText.Text); 

और फिर किसी भी तरह यह एक अभिव्यक्ति में परिवर्तित हो गए हैं ... यह संभव है? या क्या मुझे सिर्फ बुलेट काटने और विभिन्न अभिव्यक्तियों को बनाने के लिए आवश्यक सभी स्विच() कथन उत्पन्न करना चाहिए?

+0

http://stackoverflow.com/questions/1810808/linq-the-dynamic-query-or -how-to-get-an-अज्ञात-संख्या-कॉलम – Luiscencio

उत्तर

8

आप निश्चित रूप से अभिव्यक्ति को गतिशील रूप से बना सकते हैं, लेकिन मैं पहले विकल्प के रूप में Dynamic LINQ का उपयोग करने पर विचार करता हूं, हालांकि आप कंटेन का उपयोग करने में सक्षम नहीं हो सकते हैं। इसके अतिरिक्त, आप जटिल प्रश्नों को जोड़ने के लिए PredicateBuilder का उपयोग करने पर विचार करना चाह सकते हैं।

+0

मैं डायनामिक लिंक लाइब्रेरी का उपयोग करने के लिए सहमत हूं। एक बड़ा बदसूरत आज काम करेगा, लेकिन सड़क को बनाए रखने/प्रबंधित करने के लिए कठिन है। –

+0

गतिशील लिंक पूरी तरह से काम करता है। यह फ़ील्ड को भी संभालता है। कंटेनर और फील्ड! कंटेनर। जो अच्छा है, क्योंकि मैं प्रिडिकेटबिल्डर के सिर या पूंछ नहीं बना सकता। – Dave

+0

क्या मुझे vs210 .net4.0 में PredicateBuilder प्राप्त करने के लिए कुछ डाउनलोड करने की आवश्यकता है? – guiomie

4

इस कोड की कोशिश ...

कॉल ToExpression विधि() ....

public static Expression<Func<T, bool>> ToExpression<T>(string andOrOperator, string propName, string opr, string value, Expression<Func<T, bool>> expr = null) 
    { 
     Expression<Func<T, bool>> func = null; 
     try 
     { 
      ParameterExpression paramExpr = Expression.Parameter(typeof(T)); 
      var arrProp = propName.Split('.').ToList(); 
      Expression binExpr = null; 
      string partName = string.Empty; 
      arrProp.ForEach(x => 
      { 
       Expression tempExpr = null; 
       partName = partName.IsNull() ? x : partName + "." + x; 
       if (partName == propName) 
       { 
        var member = NestedExprProp(paramExpr, partName); 
        var type = member.Type.Name == "Nullable`1" ? Nullable.GetUnderlyingType(member.Type) : member.Type; 
        tempExpr = ApplyFilter(opr, member, Expression.Convert(ToExprConstant(type, value), member.Type)); 
       } 
       else 
        tempExpr = ApplyFilter("!=", NestedExprProp(paramExpr, partName), Expression.Constant(null)); 
       if (binExpr != null) 
        binExpr = Expression.AndAlso(binExpr, tempExpr); 
       else 
        binExpr = tempExpr; 
      }); 
      Expression<Func<T, bool>> innerExpr = Expression.Lambda<Func<T, bool>>(binExpr, paramExpr); 
      if (expr != null) 
       innerExpr = (andOrOperator.IsNull() || andOrOperator == "And" || andOrOperator == "AND" || andOrOperator == "&&") ? innerExpr.And(expr) : innerExpr.Or(expr); 
      func = innerExpr; 
     } 
     catch { } 
     return func; 
    } 

    private static MemberExpression NestedExprProp(Expression expr, string propName) 
    { 
     string[] arrProp = propName.Split('.'); 
     int arrPropCount = arrProp.Length; 
     return (arrPropCount > 1) ? Expression.Property(NestedExprProp(expr, arrProp.Take(arrPropCount - 1).Aggregate((a, i) => a + "." + i)), arrProp[arrPropCount - 1]) : Expression.Property(expr, propName); 
    } 

    private static Expression ToExprConstant(Type prop, string value) 
    { 
     if (value.IsNull()) 
      return Expression.Constant(value); 
     object val = null; 
     switch (prop.FullName) 
     { 
      case "System.Guid": 
       val = value.ToGuid(); 
       break; 
      default: 
       val = Convert.ChangeType(value, Type.GetType(prop.FullName)); 
       break; 
     } 
     return Expression.Constant(val); 
    } 

    private static Expression ApplyFilter(string opr, Expression left, Expression right) 
    { 
     Expression InnerLambda = null; 
     switch (opr) 
     { 
      case "==": 
      case "=": 
       InnerLambda = Expression.Equal(left, right); 
       break; 
      case "<": 
       InnerLambda = Expression.LessThan(left, right); 
       break; 
      case ">": 
       InnerLambda = Expression.GreaterThan(left, right); 
       break; 
      case ">=": 
       InnerLambda = Expression.GreaterThanOrEqual(left, right); 
       break; 
      case "<=": 
       InnerLambda = Expression.LessThanOrEqual(left, right); 
       break; 
      case "!=": 
       InnerLambda = Expression.NotEqual(left, right); 
       break; 
      case "&&": 
       InnerLambda = Expression.And(left, right); 
       break; 
      case "||": 
       InnerLambda = Expression.Or(left, right); 
       break; 
      case "LIKE": 
       InnerLambda = Expression.Call(left, typeof(string).GetMethod("Contains", new Type[] { typeof(string) }), right); 
       break; 
      case "NOTLIKE": 
       InnerLambda = Expression.Not(Expression.Call(left, typeof(string).GetMethod("Contains", new Type[] { typeof(string) }), right)); 
       break; 
     } 
     return InnerLambda; 
    } 

    public static Expression<Func<T, object>> PropExpr<T>(string PropName) 
    { 
     ParameterExpression paramExpr = Expression.Parameter(typeof(T)); 
     var tempExpr = Extentions.NestedExprProp(paramExpr, PropName); 
     return Expression.Lambda<Func<T, object>>(Expression.Convert(Expression.Lambda(tempExpr, paramExpr).Body, typeof(object)), paramExpr); 

    } 
    public static IQueryOver<T, T> OrderBy<T>(this IQueryOver<T, T> Collection, string sidx, string sord) 
    { 
     return sord == "asc" ? Collection.OrderBy(NHibernate.Criterion.Projections.Property(sidx)).Asc : Collection.OrderBy(NHibernate.Criterion.Projections.Property(sidx)).Desc; 
    } 

    public static Expression<Func<T, TResult>> And<T, TResult>(this Expression<Func<T, TResult>> expr1, Expression<Func<T, TResult>> expr2) 
    { 
     var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>()); 
     return Expression.Lambda<Func<T, TResult>>(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters); 
    } 

    public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2) 
    { 
     var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>()); 
     return Expression.Lambda<Func<T, bool>>(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters); 
    } 
संबंधित मुद्दे