तो तार्किक रूप से हम जो करने में सक्षम होना चाहते हैं वह एक नया लैम्ब्डा बना रहा है जिसमें इसमें पहले फ़ंक्शन में इनपुट का पैरामीटर होता है, और वह शरीर जो उस पैरामीटर के साथ पहला फ़ंक्शन कॉल करता है और फिर परिणाम को पास करता है दूसरे फ़ंक्शन के पैरामीटर, और फिर उसे वापस कर देता है।
हम दोहराने कर सकते हैं कि आसानी से पर्याप्त Expression
वस्तुओं का उपयोग कर:
public static Expression<Func<T1, T3>> Combine<T1, T2, T3>(
Expression<Func<T1, T2>> first,
Expression<Func<T2, T3>> second)
{
var param = Expression.Parameter(typeof(T1), "param");
var body = Expression.Invoke(second, Expression.Invoke(first, param));
return Expression.Lambda<Func<T1, T3>>(body, param);
}
दुःख की बात है एफई और अधिकांश अन्य क्वेरी प्रदाताओं वास्तव में क्या है कि के साथ क्या करना पता नहीं होगा और ठीक ढंग से काम नहीं करेगा। जब भी उन्होंने अभिव्यक्ति को मारा तो वे आम तौर पर किसी प्रकार का अपवाद फेंक देते हैं। कुछ हालांकि इसे संभाल सकते हैं। सिद्धांत रूप में उन्हें आवश्यक सभी जानकारी वहां है, अगर वे इसे पाने के लिए मजबूती से लिखे गए हैं।
हालांकि हम क्या कर सकते हैं, एक वैचारिक दृष्टिकोण से, उस लैम्ब्डा के शरीर में पहले लैम्ब्डा के पैरामीटर के प्रत्येक उदाहरण को प्रतिस्थापित करने वाले नए लैम्ब्डा के पैरामीटर के साथ प्रतिस्थापित करें, और फिर दूसरे लैम्ब्डा के पैरामीटर के सभी उदाहरणों को प्रतिस्थापित करें पहले लैम्ब्डा के नए शरीर के साथ दूसरे लैम्ब्डा में। तकनीकी रूप से, यदि इन अभिव्यक्तियों के दुष्प्रभाव होते हैं, और इन पैरामीटरों का एक से अधिक बार उपयोग किया जाता है, तो वे समान नहीं होंगे, लेकिन इन्हें ईएफ क्वेरी प्रदाता द्वारा पार्स किया जा रहा है, उन्हें वास्तव में कभी भी दुष्प्रभाव नहीं होने चाहिए।
this related question पर एक लिंक प्रदान करने के लिए डेविड बी को धन्यवाद जो ReplaceVisitor
कार्यान्वयन प्रदान करता है। हम अभिव्यक्ति के पूरे पेड़ के माध्यम से जाने के लिए ReplaceVisitor
का उपयोग कर सकते हैं और एक अभिव्यक्ति को दूसरे के साथ प्रतिस्थापित कर सकते हैं। उस प्रकार के कार्यान्वयन है:
class ReplaceVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public ReplaceVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}
और अब हम हमारे उचितCombine
विधि लिख सकते हैं:
public static Expression<Func<T1, T3>> Combine<T1, T2, T3>(
Expression<Func<T1, T2>> first,
Expression<Func<T2, T3>> second)
{
var param = Expression.Parameter(typeof(T1), "param");
var newFirst = new ReplaceVisitor(first.Parameters.First(), param)
.Visit(first.Body);
var newSecond = new ReplaceVisitor(second.Parameters.First(), newFirst)
.Visit(second.Body);
return Expression.Lambda<Func<T1, T3>>(newSecond, param);
}
और एक साधारण परीक्षण का मामला, बस प्रदर्शित करने के लिए क्या हो रहा है:
Expression<Func<MyObject, string>> fn1 = x => x.PossibleSubPath.MyStringProperty;
Expression<Func<string, bool>> fn2 = x => x.Contains("some literal");
var composite = Combine(fn1, fn2);
Console.WriteLine(composite);
जो प्रिंट करेगा:
परम => param.PossibleSubPath.MyStringProperty.Contains ("कुछ शाब्दिक")
है कौन सा हम वास्तव में क्या चाहते हैं; एक प्रश्न प्रदाता को पता चलेगा कि इस तरह कुछ कैसे पार्स करना है।
अभिव्यक्ति हेरफेर/संयोजन दिखाते हुए एक उत्तर दिया गया है। http://stackoverflow.com/a/9683506/8155 –
@ डेविड बी लिंक के लिए धन्यवाद; मुझे एक अभिव्यक्ति के सभी उदाहरणों को दूसरे के साथ बदलने के तरीके को समझने में परेशानी हो रही थी। – Servy
बहुत बहुत धन्यवाद, दोस्तों! –