2013-03-04 24 views
6

मैं नहीं जिस तरह से अभिव्यक्ति < समारोह < टी 1 से कन्वर्ट करने के लिए, प्राप्त कर सकते हैं bool > > अभिव्यक्ति < समारोह < टी 2 के लिए, bool > >। चूंकि मैं बहुत सारे प्रतिबिंब का उपयोग कर रहा हूं, असल में, मुझे वास्तव में जो चाहिए वह एक विधि है जो एक प्रकार पैरामीटर लेती है और रूपांतरण करती है।अभिव्यक्ति <समारोह <T1,bool>> अभिव्यक्ति करने के लिए <समारोह <T2,bool> कन्वर्ट गतिशील

public object Convert(Expression<Func<T1,bool>> expr, Type t); 

टी 2 टी 1

से
public class T1 { 
    int FamilyId {get; set;} 
} 

public class T2 : T1 { 
    ... other properties 
} 

मैं आधार वर्ग

Expression<Func<T1,bool>> filter = p => p.FamilyId == [some value] 

कि मैं < टी 2 एक सूची को लागू करना चाहते पर एक फिल्टर अभिव्यक्ति को परिभाषित कर रहा हूँ ली गई है >

+0

'मुझे वास्तव में जो चाहिए वह एक तरीका है जो एक प्रकार पैरामीटर लेता है और रूपांतरण करता है।' - क्या? के लिए 'बूल' क्या है? क्या आपको एक रूपांतरण विधि चाहिए? या एक सशर्त एक? मुझे समझ में नहीं आता –

+1

'टी 1' और' टी 2' कैसे संबंधित हैं? क्या उनके बीच बदलने का कोई तरीका है? – cdhowie

+0

टी 2 टी 1 से लिया गया है। – Hernan

उत्तर

9

क्या आप यह देख रहे हैं? विधि के दो स्वाद हैं: पहला आपको नए इनपुट प्रकार में तर्क के रूप में पास करने देता है; दूसरा आपको एक सामान्य पैरामीटर के रूप में इनपुट प्रकार में पास करने देता है और दृढ़ता से टाइप किए गए LambdaExpression प्राप्त करता है।

public static LambdaExpression ChangeInputType<T, TResult>(Expression<Func<T, TResult>> expression, Type newInputType) 
    { 
     if (!typeof(T).IsAssignableFrom(newInputType)) 
      throw new Exception(string.Format("{0} is not assignable from {1}.", typeof(T), newInputType)); 
     var beforeParameter = expression.Parameters.Single(); 
     var afterParameter = Expression.Parameter(newInputType, beforeParameter.Name); 
     var visitor = new SubstitutionExpressionVisitor(beforeParameter, afterParameter); 
     return Expression.Lambda(visitor.Visit(expression.Body), afterParameter); 
    } 

    public static Expression<Func<T2, TResult>> ChangeInputType<T1, T2, TResult>(Expression<Func<T1, TResult>> expression) 
    { 
     if (!typeof(T1).IsAssignableFrom(typeof(T2))) 
      throw new Exception(string.Format("{0} is not assignable from {1}.", typeof(T1), typeof(T2))); 
     var beforeParameter = expression.Parameters.Single(); 
     var afterParameter = Expression.Parameter(typeof(T2), beforeParameter.Name); 
     var visitor = new SubstitutionExpressionVisitor(beforeParameter, afterParameter); 
     return Expression.Lambda<Func<T2, TResult>>(visitor.Visit(expression.Body), afterParameter); 
    } 

    public class SubstitutionExpressionVisitor : ExpressionVisitor 
    { 
     private Expression before, after; 
     public SubstitutionExpressionVisitor(Expression before, Expression after) 
     { 
      this.before = before; 
      this.after = after; 
     } 
     public override Expression Visit(Expression node) 
     { 
      return node == before ? after : base.Visit(node); 
     } 
    } 
+2

उत्कृष्ट से लिया गया है! ठीक वही जो मेरे द्वारा खोजा जा रहा था। धन्यवाद!!!! – Hernan

+0

क्या यह समान अभिव्यक्ति कर सकता है जब टी 2 टी 1 से प्राप्त नहीं होता है? –

0

जो आप पूछ रहे हैं वह बहुत मूर्ख है। संकलक को कभी पता चलेगा कि टी 1 को टी 2 में परिवर्तित किया जा सकता है या नहीं? भयंकर रन-टाइम त्रुटियों के लिए पूछ रहा है, भले ही यह संभव है की तरह लगता है। *

(* मैं नहीं इसके संभावित जब से तुम नेस्टेड सामान्य प्रकार के साथ कलेवा गठबंधन करने के लिए कोशिश कर रहे हैं लगता है।)

+0

टी 2 टी 1 – Hernan

0

यह आप की तरह लग रहा 2 अभिव्यक्तियों को जोड़ना चाहते हैं - T2 से T1 रूपांतरण और expr पर दिए गए परिणाम के साथ कॉल करें।

यह प्रश्न सामान्य रूप से Combining two expressions (Expression<Func<T, bool>>) पर चर्चा करता है। आपके मामले में मुझे लगता है कि आपको रूपांतरण अभिव्यक्ति बनाने के लिए Expression.Call की आवश्यकता है और फिर रूपांतरण के परिणामस्वरूप मूल अभिव्यक्ति को कॉल करने के लिए।

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