2012-06-06 15 views
5

इस excellent answer पर निम्नलिखित के बाद, मुझे आश्चर्य है कि dynamic कीवर्ड का उपयोग कर डीएलआर जेनरेट असेंबली के लिए कोड लिखने के कम वर्बोज़ तरीके की अनुमति दे सकता है।CompileAssemblyFromSource के साथ जेनरेट कोड चलाने के लिए डीएलआर का उपयोग करें?

उदाहरण के लिए, ऊपर उल्लिखित जवाब के कोड कर सकते हैं:

using (Microsoft.CSharp.CSharpCodeProvider foo = 
      new Microsoft.CSharp.CSharpCodeProvider()) 
{ 
    var res = foo.CompileAssemblyFromSource(
     new System.CodeDom.Compiler.CompilerParameters() { 
      GenerateInMemory = true 
     }, 
     "public class FooClass { public string Execute() { return \"output!\";}}" 
    ); 

    var type = res.CompiledAssembly.GetType("FooClass"); 
    dynamic obj = Activator.CreateDynamicInstance(type); 
    var output = obj.Execute(); 
} 
+1

हां, थोड़ा कम कोड है। इसके बजाय 'Activator.CreateInstance()' का उपयोग करके इसे काम करें। मुझे अन्यथा कोई सवाल नहीं दिख रहा है। –

+1

हां मैंने अभी कोशिश की और महसूस किया कि यह 'var' के बजाय' गतिशील 'के साथ "बस काम करता है"। बहुत अच्छी चीजें। –

उत्तर

7

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

public interface IFoo 
{ 
    string Execute(); 
} 

तब गतिशील रूप से इस तरह विधानसभा संकलन: उदाहरण के लिए, एक अंतरफलक बनाने

using (Microsoft.CSharp.CSharpCodeProvider foo = new Microsoft.CSharp.CSharpCodeProvider()) 
{ 
    var params = new System.CodeDom.Compiler.CompilerParameters(); 
    params.GenerateInMemory = true; 

    // Add the reference to the current assembly which defines IFoo 
    params.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location); 

    // Implement the IFoo interface in the dynamic code 
    var res = foo.CompileAssemblyFromSource(params, "public class FooClass : IFoo { public string Execute() { return \"output!\";}}"); 
    var type = res.CompiledAssembly.GetType("FooClass"); 

    // Cast the created object to IFoo 
    IFoo obj = (IFoo)Activator.CreateInstance(type); 

    // Use the object through the IFoo interface 
    obj.Execute(); 
} 

कितना नियंत्रण गतिशील कोड पर है के आधार पर, इस या संभव नहीं हो सकता सकता है, लेकिन जब ऐसा होता है, तो संकलन-समय टाइप-जांच करना अच्छा होता है। उदाहरण के लिए, अमल करने के लिए आप की कोशिश की है, तो: दूसरी पंक्ति तुरंत जबकि डायनामिक कीवर्ड या प्रतिबिंब के साथ, उस रेखा को सफलतापूर्वक संकलन होता है, संकलित करने के लिए विफल हो जाएगा

IFoo obj = (IFoo)Activator.CreateInstance(type); 
obj.Execcute(); 

ऐसा इसलिए है क्योंकि यह गलत वर्तनी लेकिन यह एक रन-टाइम का कारण होगा अपवाद। उदाहरण के लिए, निम्नलिखित संकलन-समय त्रुटि नहीं मिलेगी:

dynamic obj = Activator.CreateDynamicInstance(type); 
obj.Execcute(); 
+0

विस्तृत उत्तर (+1) के लिए धन्यवाद, लेकिन मुझे आपके कथन से असहमत होना है "जबकि इसे इस तरह से करना अधिक सुविधाजनक है, न तो रास्ता टाइप-सुरक्षित है"। बाध्यकारी त्रुटियां हो सकती हैं क्योंकि प्रकार सुरक्षा सुनिश्चित की जाती है। आपका कथन विपरीत परिदृश्य के साथ सही होगा जहां कोई बाध्यकारी त्रुटि नहीं होगी जब चाहिए। –

+0

मुझे यकीन नहीं है कि आपका क्या मतलब है, लेकिन मैंने इसे और अधिक स्पष्ट करने के लिए अपना उत्तर संशोधित किया। –

+0

मेरा मानना ​​है कि मैं यह कहकर काफी स्पष्ट था कि आप यह कहकर गलत थे कि दृष्टिकोण सुरक्षित नहीं है। –

0

परिदृश्यों कि डीएलआर के लिए डिजाइन किया गया था में से एक है कि:

using (Microsoft.CSharp.CSharpCodeProvider foo = 
      new Microsoft.CSharp.CSharpCodeProvider()) 
{ 
    var res = foo.CompileAssemblyFromSource(
     new System.CodeDom.Compiler.CompilerParameters() { 
      GenerateInMemory = true 
     }, 
     "public class FooClass { public string Execute() { return \"output!\";}}" 
    ); 

    var type = res.CompiledAssembly.GetType("FooClass"); 
    var obj = Activator.CreateInstance(type); 
    var output = type.GetMethod("Execute").Invoke(obj, new object[] { }); 
} 

की तरह कुछ हो गया है। .GetMethod() और .Invoke() मैन्युअल रूप से कॉल करने से सभी अतिरिक्त टाइपिंग से बचते समय आप गतिशील रूप से लोड किए गए प्रकार के सदस्यों को आमंत्रित करने के लिए इसका उपयोग कर सकते हैं।

+0

कैसे, बिल्कुल? । । । –

+0

ठीक उसी तरह जैसा कि प्रश्न इसके उदाहरण में दिखाया गया है। प्रत्येक में पिछले दो पंक्तियों के बीच मतभेदों पर ध्यान दें। –