2010-09-08 17 views
10

वहाँ रहने दो:कन्वर्ट अभिव्यक्ति पेड़

Expression<Func<Message, bool>> exp1 = x => x.mesID == 1; 
Expression<Func<MessageDTO, bool>> exp2 = x => x.mesID == 1; 

अब मैं मैं संदेश का प्रकार बदलने की आवश्यकता _db.Messages.where(exp1); समस्या का exp1 पास करनी होगी मैं केवल exp2 है जाता है, सभी गुण एक ही कर रहे हैं!

अब मैं ऐसा करते हैं: इस के साथ

var par = Expression.Parameter(typeof(Message)); 
    var ex = (Expression<Func<Message, bool>>)Expression.Lambda(exp2.Body, par); 

समस्या इनपुट पैरामीटर बदल जाती है हाँ! लेकिन लैम्ब्डा "x.mesID" के शरीर के अंदर एक्स पुराने प्रकार का है।

शरीर में सभी पैरामीटर प्रकार को बदलने या इनपुट पैरामीटर को बदलने के किसी भी तरीके से शरीर को भी प्रतिबिंबित करता है?

मुझे लगता है कि यह हमेशा एक बड़ी समस्या है जो मेरे पास LINQ के साथ है, क्योंकि परतों के बीच मैं जेनरेट कक्षाओं को पार नहीं कर सकता, क्योंकि यह परतों को जोड़ देगा, इसलिए मुझे हल्के वजन वर्ग बनाना होगा, अब मैं एक विधि का उपयोग कैसे करूं _db.Messages.where() की तरह; busiess परत से !! !! जबकि busniess परत संदेश प्रकार के बारे में कुछ भी नहीं जानता है, यह केवल संदेश डीटीओ पता है।

+0

(जोड़ा उदाहरण) –

उत्तर

10

नहीं, मूल रूप से। अभिव्यक्ति पेड़ अपरिवर्तनीय हैं, और इसमें पूर्ण सदस्य मेटा-डेटा शामिल है (यानी mesIDmessageDTO.mesID है)। ऐसा करने के लिए, आपको अभिव्यक्ति वृक्ष को स्क्रैच (विज़िटर के माध्यम से) से पुनर्निर्माण करना होगा, जिसमें आपको समर्थन करने के लिए आवश्यक प्रत्येक नोड प्रकार को संभालना होगा।

यदि अभिव्यक्ति पेड़ मूल यह ठीक होना चाहिए, लेकिन यदि आपको पूरे गैमट का समर्थन करने की आवश्यकता है? एक विशाल पिटा (विशेष रूप से .NET 4 में, जो बहुत अधिक नोड-प्रकार जोड़ता है)।


एक बुनियादी उदाहरण है कि करता है सिर्फ क्या उदाहरण के लिए आवश्यकता होती है; आप और अधिक जटिल भाव के लिए और अधिक नोड प्रकार जोड़ने की आवश्यकता होगी:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Linq.Expressions; 
static class Program 
{ 
    static void Main() 
    { 
     Expression<Func<Message, bool>> exp1 = x => x.mesID == 1; 
     var exp2 = Convert<Message, MessageDTO>(exp1); 
    } 
    static Expression<Func<TTo, bool>> Convert<TFrom, TTo>(Expression<Func<TFrom, bool>> expr) 
    { 
     Dictionary<Expression,Expression> substitutues = new Dictionary<Expression,Expression>(); 
     var oldParam = expr.Parameters[0]; 
     var newParam = Expression.Parameter(typeof(TTo), oldParam.Name); 
     substitutues.Add(oldParam, newParam); 
     Expression body = ConvertNode(expr.Body, substitutues); 
     return Expression.Lambda<Func<TTo,bool>>(body, newParam); 
    } 
    static Expression ConvertNode(Expression node, IDictionary<Expression, Expression> subst) 
    { 
     if (node == null) return null; 
     if (subst.ContainsKey(node)) return subst[node]; 

     switch (node.NodeType) 
     { 
      case ExpressionType.Constant: 
       return node; 
      case ExpressionType.MemberAccess: 
       { 
        var me = (MemberExpression)node; 
        var newNode = ConvertNode(me.Expression, subst); 
        return Expression.MakeMemberAccess(newNode, newNode.Type.GetMember(me.Member.Name).Single()); 
       } 
      case ExpressionType.Equal: /* will probably work for a range of common binary-expressions */ 
       { 
        var be = (BinaryExpression)node; 
        return Expression.MakeBinary(be.NodeType, ConvertNode(be.Left, subst), ConvertNode(be.Right, subst), be.IsLiftedToNull, be.Method); 
       } 
      default: 
       throw new NotSupportedException(node.NodeType.ToString()); 
     } 
    } 
} 
class Message { public int mesID { get; set; } } 
class MessageDTO { public int mesID { get; set; } } 
+0

क्या आप द्वारा विज़िटर के माध्यम से मतलब है? क्या आप मुझे एक उदाहरण दे सकते हैं? – Stacker

+0

एक आगंतुक कार्यान्वयन; यानी कुछ कोड निर्माण जो आप पूरे पेड़ की संरचना को पार करने के लिए उपयोग करते हैं, आम तौर पर एक वैकल्पिक पेड़ (पत्ता नोड्स से रूट तक वापस बनाते हैं, क्योंकि प्रत्येक शाखा अपरिवर्तनीय है)। यह प्रत्येक नोड प्रकार के लिए रिकर्सिव हैंडलिंग के साथ, एक विशाल स्विच (नोड-प्रकार पर) तक उबाल सकता है। मैं एक उदाहरण चाबुक करने की कोशिश करूंगा ... –

+0

धन्यवाद मार्क यह काम करता है मुझे इसे और अधिक अभिव्यक्ति टाइप करना है – Stacker

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