2009-09-29 12 views
28

मेरे पास एक अजीब स्थिति है जहां मुझे प्रतिनिधि के नाम को स्ट्रिंग के रूप में प्राप्त करने की आवश्यकता है। मेरे पास एक सामान्य विधि है जो इस तरह दिखती है।कार्रवाई का नाम प्राप्त करें/Func प्रतिनिधि

private T Get<T>(T task, Action<T> method) where T : class 
{ 
    string methodName = method.Method.Name //Should return Bark 
} 

और मैं इसे इस

private void MakeDogBark() 
{ 
    dog = Get(dog, x=>x.Bark()); 
} 

की तरह बोल रहा हूँ लेकिन बजाय "बार्क" देखने का मैं इस "<MakeDogBark>b__19" देखते हैं। तो ऐसा लगता है कि यह मुझे विधि का नाम दे रहा है जिसने प्रतिनिधि के नाम की बजाय प्रारंभिक कॉल किया।

कोई भी यह कैसे जानता है?

उत्तर

45

यह आपको उस विधि का नाम दे रहा है जो प्रतिनिधि की कार्रवाई है। यह सिर्फ लैम्ब्डा अभिव्यक्ति का उपयोग करके कार्यान्वित किया जाता है।

आपको वर्तमान में एक प्रतिनिधि मिला है जो बदले में बार्क कॉल करता है। यदि आप सीधे Bark का उपयोग करना चाहते हैं, तो आपको Bark विधि के लिए एक खुला प्रतिनिधि बनाना होगा, जो कि बहुत सरल नहीं हो सकता है। ऐसा लगता है कि आप वास्तव में इसे कॉल करना चाहते हैं। इसे कहते आप की जरूरत नहीं है, या आप जानते हैं है कि यह वैसे भी पहले तर्क पर बुलाया जाएगा, तो आप इस्तेमाल कर सकते हैं:

private T Get<T>(T task, Action method) where T : class 
{ 
    string methodName = method.Method.Name //Should return Bark 
} 

private void MakeDogBark() 
{ 
    dog = Get(dog, dog.Bark); 
} 

आप पैरामीटर एक अभिव्यक्ति बनाकर इस दौर मिल सकता है एक प्रतिनिधि के बजाय पेड़, लेकिन फिर यह केवल तभी काम करेगा जब लैम्ब्डा अभिव्यक्ति वैसे भी एक विधि कॉल थी।

+0

कि खूबसूरती से काम किया। मुझे इसे निष्पादित करने की आवश्यकता नहीं थी, लेकिन मुझे विधि नाम को उस वर्ग में पास करना पड़ा जो इसके साथ कुछ करेगा। केवल एक स्ट्रिंग लेने के बजाय मैं चाहता था कि कॉलर की प्रकार की सुरक्षा मुझे एक असली विधि दे। हमेशा के रूप में आप आदमी हैं :) – Adam

+0

@ जोन एक सामान्य विधि के साथ ऐसा करने का कोई तरीका है? –

+0

@ अरनाब चक्रवर्ती: आपको टाइप तर्क भी निर्दिष्ट करना होगा, लेकिन मेरा मानना ​​है कि यह तब काम करेगा। हालांकि अभी इसे आसानी से आजमा सकते हैं। –

5

आप पैरामीटर के बजाय एक अभिव्यक्ति एक प्रतिनिधि बनाकर विधि कॉल के नाम प्राप्त कर सकते हैं जॉन की तरह उल्लेख किया

private T Get<T>(T task, Expression<Action<T>> method) where T : class 
{ 
    if (method.Body.NodeType == ExpressionType.Call) 
    { 
     var info = (MethodCallExpression)method.Body; 
     var name = info.Method.Name; // Will return "Bark" 
    } 

    //..... 
} 
+2

तो आप कह रहे हैं कि इसे ' (x => x.DoSomething (Arg1))' कहा जाएगा? क्या होगा यदि आप सिर्फ एक प्रकार के सुरक्षित तरीके से एक प्रतिनिधि के रूप में विधि को पास करना चाहते थे, लेकिन इसे बिना किसी आविष्कार किए, इस तरह ' (x => x.DoSomething) प्राप्त करें? – bflemi3

+0

हां। अनिवार्य रूप से, सी # 5 में सी # 6 से 'nameof' ऑपरेटर करने का कोई तरीका है? –

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