तो, अगर मैं तुम्हें सही ढंग से समझ, आप चाहते हैं
Func<Func<DateTime,string>, DateTime, string> requiredLambda = (f, dt) =>
{
var formattedDate = f.Invoke(dt);
/**
* The logic is not important here - what is important is that I
* am using the result of the executed lambda expression.
* */
var builder = new StringBuilder();
builder.Append(formattedDate);
builder.Append(" Hello!");
return builder.ToString();
};
तो फिर आप अपने इनपुट अभिव्यक्ति है एक लैम्ब्डा (अभिव्यक्ति) बनाने के लिए जो आपके पास किए गए फ़ंक्शन का उपयोग करता है और इसके आसपास कुछ अतिरिक्त काम करता है। तो आप अनिवार्य रूप से सिर्फ एक अभिव्यक्ति के अंदर इस समारोह का उपयोग करना चाहते हैं।
इस बिंदु पर, मुझे यह सुझाव देने की अनुमति दें कि आप अभिव्यक्तियों का भी उपयोग नहीं करते हैं। आप केवल एक ऐसा फ़ंक्शन बना सकते हैं जो Func<DateTime, string>
पैरामीटर लेता है और कुछ संसाधित करने के लिए इसका उपयोग करता है। लेकिन अगर आपको वास्तव में कुछ के लिए अभिव्यक्ति की आवश्यकता है, तो मैं बस एक बनाने के तरीके को समझाने की कोशिश करूंगा।
इस उदाहरण के लिए, मैं इस समारोह बना रहे होते हैं:
string MonthAndDayToString (int month, int day)
{
return "'" + formattingFunction(new DateTime(2013, month, day)) + "'"
}
आप देख सकते हैं, मैं एक Func<int, int, string>
जो तब DateTime
वस्तु बनाता है और समारोह और उसके बाद को पास कर बनाने के लिए जा रहा हूँ आगे परिणाम बदलता है।
Func<DateTime, string> formatting = dt => (...) // as above
// define parameters for the lambda expression
ParameterExpression monthParam = Expression.Parameter(typeof(int));
ParameterExpression dayParam = Expression.Parameter(typeof(int));
// look up DateTime constructor
ConstructorInfo ci = typeof(DateTime).GetConstructor(new Type[] { typeof(int), typeof(int), typeof(int) });
// look up string.Concat
MethodInfo concat = typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string), typeof(string) });
// inner call: formatting(new DateTime(2013, month, day))
var call = Expression.Call(formatting.Method, Expression.New(ci, Expression.Constant(2013), monthParam, dayParam));
// concat: "'" + call + "'"
var expr = Expression.Call(concat, Expression.Constant("'"), call, Expression.Constant("'"));
// create the final lambda: (int, int) => expr
var lambda = Expression.Lambda<Func<int, int, string>>(expr, new ParameterExpression[] { monthParam, dayParam });
// compile and execute
Func<int, int, string> func = lambda.Compile();
Console.WriteLine(func(2, 1)); // '01.02.2013 Hello!'
Console.WriteLine(func(11, 26)); // '26.11.2013 Hello!'
एलेक्स 'जवाब को देखने के बाद ऐसा लगता है कि मैं अपने प्रश्न को गलत समझा और आप क्या कर रहे हैं रिवर्स का समाधान करने की कोशिश की। लेकिन यह आप वास्तव में क्या करने के लिए कोशिश कर रहे हैं करने के लिए इसे बदलने के लिए सब भी अलग नहीं है:
Func<DateTime, string> formatting = dt => dt.ToShortDateString();
ParameterExpression param = Expression.Parameter(typeof(DateTime));
MethodInfo concat = typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string), typeof(string) });
var call = Expression.Call(formatting.Method, param);
var expr = Expression.Call(concat, Expression.Constant("'"), call, Expression.Constant(" Hello!'"));
var lambda = Expression.Lambda<Func<DateTime, string>>(expr, new ParameterExpression[] { param });
Func<DateTime, string> func = lambda.Compile();
Console.WriteLine(func(new DateTime(2013, 02, 01)));
Console.WriteLine(func(new DateTime(2013, 11, 26)));
लेकिन मैं अभी भी लोगों का तर्क होता है कि एक सामान्य समारोह है कि एक Func<DateTime, string>
और एक DateTime
पैरामीटर लेता है बनाए रखने के लिए एक बहुत आसान होगा । तो जब तक आप को वास्तव में अभिव्यक्तियों की आवश्यकता नहीं है, तो उनसे बचें।
मुझे अभी भी क्यों नहीं लगता कि आपको इसके लिए अभिव्यक्ति की आवश्यकता है। इस उदाहरण पर विचार:
private Func<DateTime, string> formatting = dt => dt.ToShortDateString();
private Func<DateTime, string> formattingLogic = null;
public Func<DateTime, string> FormattingLogic
{
get
{
if (formattingLogic == null)
{
// some results from reflection
string word = "Hello";
string quote = "'";
formattingLogic = dt =>
{
StringBuilder str = new StringBuilder(quote);
str.Append(formatting(dt));
if (!string.IsNullOrWhiteSpace(word))
str.Append(" ").Append(word);
str.Append(quote);
return str.ToString();
};
}
return formattingLogic;
}
}
void Main()
{
Console.WriteLine(FormattingLogic(new DateTime(2013, 02, 01))); // '01.02.2013 Hello'
Console.WriteLine(FormattingLogic(new DateTime(2013, 11, 26))); // '26.11.2013 Hello'
}
आप देख सकते हैं, मैं केवल स्वरूपण तर्क समारोह एक बार का निर्माण कर रहा हूँ, lazily जब यह अभी तक स्थापित नहीं किया गया। वह तब होता है जब प्रतिबिंब कुछ मूल्य प्राप्त करने के लिए चलता है जिसे आप फ़ंक्शन में कहीं भी उपयोग कर रहे हैं। चूंकि फ़ंक्शन को लैम्ब्डा फ़ंक्शन के रूप में बनाया गया है, लैम्बडा फ़ंक्शन के भीतर स्थानीय दायरे से उपयोग किए जाने वाले चर स्वचालित रूप से कैप्चर किए जाते हैं और उपलब्ध रहते हैं।
अब निश्चित रूप से आप इसे अभिव्यक्ति के रूप में भी बना सकते हैं और संकलित फ़ंक्शन को स्टोर कर सकते हैं, लेकिन मैं तर्क दूंगा कि ऐसा करने से यह बहुत अधिक पठनीय और रखरखाव योग्य है।
मुझे समझ में नहीं आता है। अभिव्यक्ति वृक्ष के अंदर आप 'formattingExpression.Compile()' को क्यों कॉल नहीं कर सकते? – svick