2009-08-18 14 views
5

मैं एक सी # विधि है कि एक तर्क के रूप में एक स्ट्रिंग लेता है के रूप में पारित किया गया था, कि स्ट्रिंग एक स्थिर विधि जैसेएक विधि भागो thats नाम एक स्ट्रिंग

"MyClass.GetData" 

का नाम है यह है कि विधि को चलाने के लिए संभव है स्ट्रिंग में पारित मूल्य से?

typeof (MyClass).GetMethod (MyClass.GetData) // Assuming get data is the string name. 

यह एक MethodInfo वर्ग आप में लौट आएंगे:

+0

+1 मुझे देखने और कुछ और सीखने के लिए +1। – Gishu

उत्तर

11

हाँ आप System.Reflection

का उपयोग कर सकते हैं
CallStaticMethod("MainApplication.Test", "Test1"); 

public static void CallStaticMethod(string typeName, string methodName) 
{ 
    var type = Type.GetType(typeName); 

    if (type != null) 
    { 
     var method = type.GetMethod(methodName); 

     if (method != null) 
     { 
      method.Invoke(null, null); 
     } 
    } 
} 

public static class Test 
{ 
    public static void Test1() 
    { 
     Console.WriteLine("Test invoked"); 
    } 
} 
+0

अच्छा उदाहरण; मैं लगभग बिल्कुल पोस्ट करने वाला था एक ही कोड (मेरे संस्करण में केवल अंतर यह है कि CallStaticMethod केवल एक स्ट्रिंग लेता है और विधि नाम से अलग प्रकार के लिए आंतरिक रूप से इसे चॉप करता है, और यह विधि का परिणाम भी देता है)। –

1

आप की तरह कुछ की कोशिश कर सकते। उस से, आप Invoke विधि (दाएं पैराम के साथ) का उपयोग कर सकते हैं।

+2

इस नमूने के साथ कई समस्याएं हैं, प्रमुख यह है कि यह संकलित नहीं होगा, क्योंकि GetMethod एक 'स्ट्रिंग' तर्क लेता है। 'गेट टाइप' के लिए एक अनावश्यक कॉल भी है; 'टाइपऑफ (MyClass) '' टाइप' ऑब्जेक्ट देता है। उस ऑब्जेक्ट पर 'गेट टाइप' का आह्वान करने से 'MyClass' की बजाय 'टाइप'' का वर्णन करने वाली 'टाइप' ऑब्जेक्ट' वापस आ जाएगी, और 'GetData' विधि नहीं मिलनी चाहिए। –

+0

इरादा सही है - कोड – Gishu

+0

माफी नहीं है, दूसरे पास के साथ पहले पास किए गए पहले पास का परिणाम था ... मेरा इन-निर्मित सी # कंपाइलर असफल रहा (; – Kieron

1

उत्तर प्रतिबिंब में निहित है। आप किसी निश्चित प्रकार के MethodInfo प्राप्त करने के लिए प्रतिबिंब का उपयोग कर सकते हैं। (आपको उस प्रकार को जानना है), और फिर आप इसे बुला सकते हैं।

लेकिन, क्या आप सुनिश्चित हैं कि आपकी समस्या का समाधान करने के लिए कोई बेहतर समाधान नहीं है? यह एक स्ट्रिंग के रूप में क्यों पारित किया जाता है?

2

हां आप विधि खोजने और उचित बहस के साथ आह्वान करने के लिए प्रतिबिंब का उपयोग कर सकते हैं।

2

Reflection API

class Test 
{ 
    public void Print(int n) 
    { 
     Console.WriteLine(n); 
    } 
} 
class MainA 
{ 
    static void Main() 
    { 
     Type t = typeof(Test); 
     Object obj = new Test(); 
     System.Reflection.MethodInfo m = t.GetMethod("Print"); 
     m.Invoke(obj,new object[]{11}); 
    } 
} 
1

प्रतिबिंब बुनियादी उपकरण आप की जरूरत है, लेकिन आप अभी भी (इसे विभाजित स्ट्रिंग अपने आप को पार्स करने के लिए की आवश्यकता होगी बिंदुओं पर और आवश्यक MethodInfo के लिए इसे सभी तरह से प्रतिबिंबित करें)। हालांकि आपको ध्यान रखना चाहिए कि इस तरह के एक ऑपरेशन का प्रदर्शन प्रत्यक्ष विधि आमंत्रण की तुलना में कई हंड्रेड (यदि हजार या अधिक नहीं) धीमा है। यह कुछ बार करना ठीक है, लेकिन यदि आप ऐसा करने का इरादा रखते हैं, तो आपको वास्तव में इस तरह से अपने कोड को पुन: सक्रिय करने पर विचार करना चाहिए कि यह आवश्यक नहीं है।

यदि आप वास्तव में इससे बच नहीं सकते हैं (और ज्यादातर मामलों में आप कर सकते हैं), तो आप कम से कम कुछ शब्दकोश में पाए गए MethodInfo ऑब्जेक्ट्स को कैश करके इसे गति दे सकते हैं। इस तरह आपको हर बार प्रतिबिंबित नहीं करना पड़ेगा।

इसके अलावा, यदि आप उनके बारे में नहीं जानते हैं, तो मैं delegates को देखने की सलाह दूंगा। संभावना है कि यह आपकी समस्या का उत्तर है। और यह प्रत्यक्ष विधि कॉल के रूप में लगभग तेज़ है।

0

हां। केवल एक चीज यह है कि आपको कक्षा के नामस्थान को भी आपूर्ति करने की आवश्यकता होगी।

हैथ ने इसे काफी पसंद किया है। जब से मैं (अस्थायी, नाम स्थान है उपयोगकर्ता classname है और मौजूद है इसके भीतर एक सार्वजनिक स्थैतिक विधि है।)

private static object ExecuteStaticMethod(string method_full_path, object[] args) 
     { 
     var tokens = method_full_path.Split('.'); 
     string class_full_name = String.Format("{0}.{1}", tokens[0], tokens[1]); 
     var class_blueprint = Assembly.GetExecutingAssembly().GetType(class_full_name); 
     var handle_to_method = class_blueprint.GetMethod(tokens[2], BindingFlags.Default | BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public); 
     return handle_to_method.Invoke(null, args); 

     } 

     public static void Main(string[] args) 
     { 
     Console.WriteLine(ExecuteStaticMethod("temp.User.Exists", new object[] {"Gishu"})); // prints false 
     User.Create("Gishu"); 
     Console.WriteLine(ExecuteStaticMethod("temp.User.Exists", new object[] { "Gishu" })); // prints true 
     } 
1

यह मेरी संस्करण .. यहाँ पूरा लिखने की मुसीबत ले लिया प्रतिबिंब के रास्ते नीचे जाने से पहले, जो आप करना चाहते हैं उसे बुलाया जाता है, सुनिश्चित करें कि इसे लागू करने का कोई और बेहतर तरीका नहीं है। प्रतिनिधियों को सबसे पहले चेक करें, क्योंकि वे रनटाइम पर सेट की गई विधि को कॉल कर सकते हैं।

तो यहाँ आप प्रतिबिंब के लिए जाना:

public void MyFunction() 
{ 
    string dotSeparatedParams = "Myclass.Method"; 
    string[] arrayParams = dotSeparatedParams.Split('.'); 
    // since the class was defined in the string, start with loading it 
    Type classType = Type.GetType(arrayParams[0]); 
    if(classType == null) 
     throw new Exception(); 
    // load the reference to the method 
    MethodInfo mi = classType.GetMethod(arrayParams[1]); 
    if (mi == null) 
     throw new Exception(); 
    // call the method 
    mi.Invoke(null, null); 
} 

कुछ नोट:

  • इस उदाहरण में, अपने विधि स्थिर होना चाहिए। कारण यह है कि हम 'MyClass' को नहीं बढ़ा रहे हैं। ऐसा करना संभव है, लेकिन इसके लिए कोई पैरामीटर के साथ एक डिफ़ॉल्ट नियंत्रक की आवश्यकता है। उस के लिए .GetConstructor देखो। लेकिन आम तौर पर, एक विधि को कॉल करने के लिए फ्लाई पर कक्षा बनाने की सलाह नहीं दी जाती है।
  • स्थैतिक विधि मेरे उदाहरण में कोई पैरामीटर नहीं लेती है। यदि ऐसा होता है, तो वस्तुओं के सरणी के साथ mi.Invoke (...) के दूसरे तर्क को प्रतिस्थापित करें: नई ऑब्जेक्ट [2] {232, "एक स्ट्रिंग"}
  • आप उस ऑब्जेक्ट को पास कर सकते हैं जिस पर आप चाहते हैं इसके बजाए विधि को कॉल करें। आपके पास MyFunction के लिए पैरामीटर होगा जो 'MyClass' प्रकार की ऑब्जेक्ट लेता है और आप उस ऑब्जेक्ट को mi.Invoke() कॉल पर पास करेंगे।
संबंधित मुद्दे