2016-10-25 5 views
8

मेरे पास कुछ मामले हैं जहां मुझे कक्षा के नाम से विधि नामों को कॉल करना है।गतिशील रूप से कॉलिंग विधि और कक्षा का नाम

string scenario1 = "MockScenario1"; 
string scenario2 = "MockScenario2"; 

MockScenario1.GetInfo(); 
MockScenario2.GetInfo(); 

मैं गतिशील रूप से की तरह

scenario1.GetInfo() 
scenario2.GetInfo() 

मैं संबंधित विकल्प खोजने के लिए स्ट्रिंग और नियंत्रण अंतरिक्ष से सभी विकल्पों को जानने की कोशिश यहां विधि नाम कॉल करने के लिए तार का उपयोग कर सकते हैं। कोई सुझाव?

मैं नीचे और वर्ग के नाम गतिशील

उत्पन्न होने की कोशिश की कोशिश की कर रहा हूँ नीचे कोड उत्पन्न विधि नाम गतिशील

string methodName = "hello"; 

//Get the method information using the method info class 
MethodInfo mi = this.GetType().GetMethod(methodName); 

//Invoke the method 
// (null- no parameter for the method call 
// or you can pass the array of parameters...) 
mi.Invoke(this, null); 

अधिक स्पष्ट परिदृश्य: मैं पैरामीटर के रूप में वर्ग के नाम भेजने के लिए कोशिश कर रहा हूँ MockScenario1 और MockScenario2 कक्षा के नाम हैं। आप कमांड डिज़ाइन पैटर्न इस्तेमाल कर सकते हैं

Type thisType = this.GetType(); 
MethodInfo theMethod =  thisType.GetMethod(FunctionName); 
theMethod.Invoke(this, userParameters); 
+1

की संभावित डुप्लिकेट [परिवर्तनीय नाम के लिए स्ट्रिंग] (http://stackoverflow.com/questions/1293549/string-to-variable-name) – Residuum

+1

निम्न लिंक देखें http://stackoverflow.com/questions/1 044455/सी-तेज-प्रतिबिंब-कैसे-प्राप्त-श्रेणी-संदर्भ-से-स्ट्रिंग –

+0

http://stackoverflow.com/a/39793450/5962841 में देखें यह कक्षा – Mafii

उत्तर

15

कैसे अपने स्ट्रिंग प्रतिनिधित्व से एक प्रकार का एक उदाहरण बनाने के लिए:

string scenario1 = "TheNamespace.MockScenario1"; 
Type theType = this.GetType().Assembly.GetType(scenario1); 
var theInstance = (MockScenario1)Activator.CreateInstance(theType); 
theInstance.GetInfo(); 

यह बेहतर होगा अपनी कक्षाओं एक आम इंटरफ़ेस को लागू अगर, उदाहरण के के लिए IGetInfoAware, और फिर आप लिख सकते हैं एक अधिक सामान्य लोडर:

var theInstance = (IGetInfoAware)Activator.CreateInstance(theType); 

नोट: उपलब्ध कराने की जरूरत है scenario1 और scenario2

के लिए पूर्ण वर्ग के नाम देखें Activator.CreateInstance

संपादित करें:

रूप @Georg ने बताया अगर प्रकार संदर्भ वस्तुओं की विधानसभा में घोषणा नहीं की है, तो यह आवश्यक है पहले विधानसभा जहां प्रकार की मेजबानी की है पाने के लिए:

var theAssembly = (
    from Assembly assembly in AppDomain.CurrentDomain.GetAssemblies() 
    where (assembly.FullName == "TheNamespace.AssemblyName") 
    select assembly 
) 
.FirstOrDefault(); 

if (theAssembly!= null){ 
    Type theType = theAssembly.GetType(scenario1); 
    var theInstance = (IGetInfoAware)Activator.CreateInstance(theType); 
    theInstance.GetInfo(); 
} 

किसी कारण से विधानसभा नाम आप के लिए अज्ञात है, तो प्रकार निम्नलिखित की तरह हल किया जा सकता है:

public Type GetTypeFromString(String typeName) 
{ 
    foreach (Assembly theAssembly in AppDomain.CurrentDomain.GetAssemblies()) 
    { 
     Type theType = theAssembly.GetType(typeName); 
     if (theType != null) 
     { 
      return theType;      
     } 
    } 
    return null; 
} 
+1

मुझे लगता है कि इस प्रकार की धारणा कि संदर्भ ऑब्जेक्ट्स प्रकार की असेंबली में स्थित है, एक डिज़ाइन दोष है। अगर किसी को एक अलग असेंबली में कक्षा विरासत में लेती है, तो यह पहले से ही व्यवहार को बदल देती है, भले ही कुछ और नहीं बदला हो। आपको क्लाइंट को उस विधानसभा को बेहतर तरीके से चुनना चाहिए जिसमें आप प्रकार खोजना चाहते हैं या आप असेंबली-योग्य प्रकार के नाम की अपेक्षा कर सकते हैं। – Georg

+0

@ जॉर्ज, यह एक अच्छा अवलोकन है, मैंने आपके द्वारा इंगित परिदृश्य से निपटने के लिए उत्तर अपडेट किया है। –

4

आप प्रतिबिंब का उपयोग कर सकते हैं। तो आप हैश मैप में कुंजी के रूप में अपनी स्ट्रिंग को स्टोर करने के लिए हैश मैप का उपयोग करेंगे, और फिर आपका फ़ंक्शन हैशैप का मान होगा। फिर जब आप अपने फ़ंक्शन को कॉल करना चाहते हैं तो आप hashmap.get ("yourString") कहते हैं। यह उस फ़ंक्शन को वापस कर देगा जिसे आपने अपने मूल्य के रूप में संग्रहीत किया है और आप उसे वहां से कॉल कर सकते हैं।

+0

इसका प्रकार का नाम स्ट्रिंग के रूप में दिया गया है, फ़ंक्शन का नाम नहीं। –

+0

यदि आप मौजूदा वर्ग – Hadi

+0

पर विधि का आह्वान नहीं करते हैं तो आपको टाइप नाम दर्ज करना चाहिए, मेरा इरादा mockscenario1,2,3 आदि पैरामीटर के रूप में पास करना है। उपरोक्त कोड के साथ मुझे क्लासनाम इम्प्लिसीटी देना है और यह कसकर बाध्य है। – Kurkula

3

:

string scenarioCats = "MockScenario1"; 
string scenarioDogs = "MockScenario2"; 
GetResult(scenarioCats); 
GetResult(scenarioDogs); 

public static void GetCatsResult(string scenarioCats){ 
scenarioCats obj = new scenarioCats(); 
    obj.GetInfo();  
} 
public static void GetDogsResult(string scenarioDogs){ 
scenarioDogs obj = new scenarioDogs(); 
    obj.GetInfo();  
} 
+0

लिखा है [इसलिए], टिप: कोड जोड़ना हमेशा एक अच्छा विचार है ... अन्य सभी उत्तरों देखें। –

3

मैं Dictionary<String, Action> का उपयोग करने का सुझाव देता हूं, जहां आप सभी परिदृश्यों और उनके नामों को नीचे डाल सकते हैं उदा।

private static Dictionary<String, Action> s_Scenario = 
    new Dictionary<String, Action>() { 
    {"MockScenario1",() => MockScenario1.GetInfo()}, 
    {"MockScenario2",() => MockScenario2.GetInfo()}, 
    }; 

... 

s_Scenario["MockScenario1"](); 
s_Scenario["MockScenario2"](); 
+1

आप '{" MockScenario1 ", MockScenario1.GetInfo}, 'सीधे' के साथ भी जोड़ सकते हैं। नोट: 'GetInfo' के बाद कोई ब्रांड्स नहीं! –

+0

@ ओलिवियर जैकोट-डेस्कोम्ब्स: आप काफी सही हैं 'मॉकसेनारियो 1। गेटइन्फो' एक टियरर समाधान है; मैंने बस यह दिखाने की कोशिश की कि * कोई भी लैब्डा * (आवश्यक एक विधि नहीं) वैध परिदृश्य के रूप में उपयोग किया जा सकता है, उदा। '{" MockScenarios1and2 ",() => {MockScenario1.GetInfo(); MockScenario2.GetInfo(); }} ' –

+0

मेरा इरादा mockscenario1,2,3 आदि को पैरामीटर के रूप में पास करना है। – Kurkula

2

NamespaceGetType() को हमेशा अशक्त लौट सकते हैं देने के बिना (मैं इस जवाब को जोड़ने से पहले कि समस्या का सामना करना पड़।), तो यह इस तरह होना चाहिए;

आप उल्लेख किया है, आप पैरामीटर

public void GetCatsResult(string scenarioCats) 
     { 
      string item = this.GetType().Namespace + "." + scenarioCats; 
      // combined class string with the namespace 
      Type className = Type.GetType(item); 
      // found the class 
      MethodInfo m = className.GetMethod("GetInfo"); 
      // get the method from class 
      object value = m.Invoke(null,null); 
      // invoke and value will represent the return value. 
     } 

यहाँ के रूप में स्ट्रिंग देना चाहता हूँ मेरी परिदृश्य वर्ग,

class Scenario1 
    { 
     public static string GetInfo() 
     { 
      return "GetInfo() called, Scenario1"; 
     } 
    } 

परिणाम है; (Btw GetCatsResult() पर कहा जाता है और स्ट्रिंग जो string scenario1 = "Scenario1"; के रूप में घोषित दी)

enter image description here

आशा में मदद करता है,

0

यदि यह आप PrivateObject उपयोग कर सकते हैं के परीक्षण के लिए है:

using Microsoft.VisualStudio.TestTools.UnitTesting; 

class Class1 
{ 
    public Class1() 
    { 
     MyClass myClass = new MyClass(); 
     PrivateObject myClassPrivateObject = new PrivateObject(myClass, new PrivateType(typeof(MyClass))); 

     myClassPrivateObject.Invoke("MyMethod"); 
    } 
} 
संबंधित मुद्दे