2011-08-09 11 views
5

मैं एक डेवलपर को क्वेरी निर्दिष्ट करने की अनुमति देने के लिए अभिव्यक्तियों का उपयोग करके एक वेब सेवा कॉल के आसपास एक एपीआई बना रहा हूं और अभिव्यक्तिविज्ञानी अभिव्यक्ति को क्वेरी स्ट्रिंग में परिवर्तित कर रहा हूं। अनुरोध एक विशेष तत्व के साथ एक्सएमएल है जिसमें एक क्वेरी स्ट्रिंग है। "या BANKNAME = 'बैंक 1' BANKNAME = 'बैंक 2'"अभिव्यक्ति को वास्तविक परिणाम में कैसे संकलित करें?

:

उदाहरण के लिए, मैं कुछ इस तरह जो बैंक 1 या बैंक 2 के एक बैंक नाम के साथ सभी की जाँच के खातों को पुनः प्राप्त करेगा कर सकते हैं

वेब सेवा काफी जटिल प्रश्नों को संभाल सकती है लेकिन मैं अभी इसके साथ रहूंगा।


[IntacctObject("checkingaccount")] 
public class CheckingAccount : Entity 
{ 
    [IntacctElement("bankaccountid")] 
    public string Id { get; set; } 

    [IntacctElement("bankname")] 
    public string BankName { get; set; } 
} 

और एक ExpressionVisitor जिसका प्राथमिक कार्य है इस तरह एक अभिव्यक्ति कन्वर्ट करने के लिए: "BANKNAME = 'बैंक 1': क्वेरी में

 
Expression> expression = ca => ca.BankName == "Bank 1" || ca.BankName == "Bank 2" 

तो मैं एक वर्ग CheckingAccount है या बैंकनाम = 'बैंक 2' "

यह इतना कठिन नहीं है। कहाँ चीजों को तोड़ने के लिए शुरू जब मैं स्थानीय चर परिचय हैं:


var account = new CheckingAccount { BankName = "Bank 1" }; 
string bankName = "Bank 2"; 

Expression> expression = ca => ca.BankName == account.BankName || ca.BankName == bankName; 

मैं एक साधारण स्थानीय चर (। यानी स्ट्रिंग BANKNAME = "बैंक 2") से निपटने के लिए कैसे पता है, लेकिन एक अन्य प्रकार के साथ काम कर (वर खाता = नया चेकिंग खाता {बैंकनाम = "बैंक 1"}) अधिक जटिल है।

दिन के अंत में ये बड़े मुद्दे हैं जिन्हें मुझे अभी समझने की आवश्यकता है कि मुझे कैसे निपटना है। मुझे पता है कि बहुत जटिल परिदृश्य हैं लेकिन मैं इस समय उन लोगों से इतना चिंतित नहीं हूं।

यहाँ मेरी अभिव्यक्ति आगंतुक है (विधि CreateFilter पर सामान्य बाधा कृपया ध्यान दें):


internal class IntacctWebService30ExpressionVisitor : ExpressionVisitor 
{ 
    private readonly List _Filters = new List(); 
    private IntacctWebServicev30SimpleQueryFilter _CurrentSimpleFilter; 
    private IntacctWebServicev30ComplexQueryFilter _CurrentComplexFilter; 
    private MemberExpression _CurrentMemberExpression; 

    public string CreateFilter(Expression> expression) where TEntity : Entity 
    { 

     Visit(expression); 

     string filter = string.Join(string.Empty, _Filters.Select(f => f.ToString()).ToArray()); 
     return filter; 
    } 

    protected override Expression VisitBinary(BinaryExpression node) 
    { 
     switch (node.NodeType) 
     { 
      case ExpressionType.AndAlso: 
      case ExpressionType.OrElse: 
       _CurrentComplexFilter = new IntacctWebServicev30ComplexQueryFilter { ExpressionType = node.NodeType }; 
       break; 
      case ExpressionType.Equal: 
      case ExpressionType.GreaterThan: 
      case ExpressionType.GreaterThanOrEqual: 
      case ExpressionType.LessThan: 
      case ExpressionType.LessThanOrEqual: 
      case ExpressionType.NotEqual: 
       _CurrentSimpleFilter = new IntacctWebServicev30SimpleQueryFilter { ExpressionType = node.NodeType }; 
       break; 
     } 

     return base.VisitBinary(node); 
    } 

    protected override Expression VisitMember(MemberExpression node) 
    { 
     var attr = node.Member.GetAttribute(); 
     if (attr != null) 
      _CurrentSimpleFilter.FieldName = attr.FieldName; 
     else 
      _CurrentMemberExpression = node; 

     return base.VisitMember(node); 
    } 

    protected override Expression VisitConstant(ConstantExpression node) 
    { 
     object value = Expression.Lambda>(node).Compile().Invoke(); 

     string fieldValue = extraxtFieldValue(value, node); 

     _CurrentSimpleFilter.FieldValue = fieldValue; 

     if (_CurrentComplexFilter != null) 
     { 
      if (_CurrentComplexFilter.Left == null) 
      { 
       _CurrentComplexFilter.Left = _CurrentSimpleFilter; 
      } 
      else if (_CurrentComplexFilter.Right == null) 
      { 
       _CurrentComplexFilter.Right = _CurrentSimpleFilter; 
       _Filters.Add(_CurrentComplexFilter); 
      } 
      else 
       throw new InvalidOperationException(); 
     } 
     else 
     { 
      _Filters.Add(_CurrentSimpleFilter); 
     } 

     return base.VisitConstant(node); 
    } 

    private string extraxtFieldValue(object value) 
    { 
     string fieldValue; 
     if (value is DateTime) 
      fieldValue = ((DateTime)value).ToString("yyyy-MM-dd"); 
     else if (value is string) 
      fieldValue = value.ToString(); 
     else if (value.GetType().IsEnum) 
     { 
      throw new NotImplementedException(); 
     } 
     else 
     { 
      // Not sure if this is the best way to do this or not but can't figure out how 
      // else to get a variable value. 

      // If we are here then we are dealing with a property, field, or variable. 
      // This means we must extract the value from the object. 
      // In order to do this we will rely on _CurrentMemberExpression 
      if (_CurrentMemberExpression.Member.MemberType == MemberTypes.Property) 
      { 
       fieldValue = value.GetType().GetProperty(_CurrentMemberExpression.Member.Name).GetValue(value, null).ToString(); 
      } 
      else if (_CurrentMemberExpression.Member.MemberType == MemberTypes.Field) 
      { 
       fieldValue = value.GetType().GetFields().First().GetValue(value).ToString(); 
      } 
      else 
      { 
       throw new InvalidOperationException(); 
      } 
     } 

     return fieldValue; 
    } 
} 

कृपया मुझे पता है अगर आप किसी भी अधिक विस्तार चाहते हैं ....

धन्यवाद

+0

क्या आपके फ़िल्टर हमेशा एंटीटी होने जा रहे हैं। बाइनरी सेशन के बाईं ओर प्रॉपर्टी? – MerickOWA

+0

वे गुण या फ़ील्ड होंगे। – devlife

+0

मुझे लगता है कि आपने अपने अन्य प्रश्न पर मेरा जवाब स्वीकार कर लिया है, क्या मेरा उत्तर आपके प्रश्नोत्तरी वर्गों को एकीकृत करने के लिए पर्याप्त स्पष्ट था? – MerickOWA

उत्तर

-1

यदि आप इसे करने के लिए ओपन सोर्स थर्ड पार्टी लाइब्रेरी का उपयोग करने में रुचि रखते हैं, तो आप Expression Tree Serialization देख सकते हैं। मेरा मानना ​​है कि यह वही करता है जो आप खोज रहे हैं।

+0

मेरा मानना ​​है कि यह नहीं है। – svick

+0

इस बात को देखते हुए कि धारावाहिक किसी भी LINQ अभिव्यक्ति को XElement में कैसे परिवर्तित करेगा, जिसे तब तार में एक एक्सएमएल स्ट्रिंग में बदल दिया जा सकता है, ऐसा लगता है कि ओप क्या करना चाहता है। आप कृपया ध्यान दे सकते हैं कि क्या कमी है, मैं बहुत बाध्य होगा। – Mranz

+0

जिस तरह से मैंने सवाल पढ़ा है, वह अभिव्यक्ति को एक बहुत ही विशिष्ट रूप में परिवर्तित करना चाहता है (उदाहरण है "बैंकनाम = 'बैंक 1' या बैंकनाम = ' बैंक 2 '' '), कुछ एक्सएमएल नहीं। – svick

0

an article about this very issue from Matt Warren पर एक नज़र डालें। वह एक वर्ग के लिए स्रोत प्रदान करता है जो वास्तव में ऐसा करता है, एक स्पष्टीकरण के साथ यह कैसे करता है। यह his IQToolkit में भी शामिल है।

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

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