2012-04-10 12 views
10

के प्रकार और कॉल कन्स्ट्रक्टर बनाएं गतिशील रूप से कक्षा बनाने की आवश्यकता है। ज्यादातर चीजें ठीक काम करती हैं लेकिन मैं कन्स्ट्रक्टर उत्पन्न करने में फंस गया हूं।गतिशील रूप से बेस-क्लास

AssemblyBuilder _assemblyBuilder = 
     AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("MyBuilder"),              AssemblyBuilderAccess.Run); 

ModuleBuilder _moduleBuilder = _assemblyBuilder.DefineDynamicModule("MyModule"); 

public static object GetInstance<TSource, TEventArgs>(this TSource source, string eventName) 
    where TSource : class 
{ 
    var typeName = "MyTypeName"; 
    var typeBuilder = _moduleBuilder.DefineType(typeName, TypeAttributes.Class | TypeAttributes.Public); 

    // create type like class MyClass : GenericType<MyClass, TSource, TEventArgs> 
    var baseNotGenericType = typeof(GenericType<,,>); 
    var baseType = baseNotGenericType.MakeGenericType(typeBuilder, typeof(TSource), typeof(TEventArgs)); 
    typeBuilder.SetParent(baseType); 


    // the base class contains one constructor with string as param 
    var baseCtor = baseNotGenericType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(string) }, null); 

    var ctor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard | CallingConventions.HasThis, new Type[0]); 
    var ilGenerator = ctor.GetILGenerator(); 

    // i want to call the constructor of the baseclass with eventName as param 
    ilGenerator.Emit(OpCodes.Ldarg_0); // push "this" 
    ilGenerator.Emit(OpCodes.Ldstr, eventName); // push the param 
    ilGenerator.Emit(OpCodes.Call, baseCtor); 
    ilGenerator.Emit(OpCodes.Ret); 

    var type = typeBuilder.CreateType(); 

    // return ... 
} 

कन्स्ट्रक्टर के कॉल पर मुझे BadImageFormatException मिल रहा है। मैं क्या गलत कर रहा हूं?

अनुरोध किया के रूप में: क्रम में एक परिणाम के रूप

public abstract class GenericType<GT, TEventSource, TEventArgs> : BaseClass 
    where GT: GenericType<GT, TEventSource, TEventArgs>, new() 
    where TEventArgs : EventArgs 
    where TEventSource : class 
{ 
    protected GenericType(string eventName) 
    { 
     _eventName = eventName; 
    } 
    // ... 
} 

मैं चाहते हैं क्या है करने के लिए:

BaseClass कुछ इस तरह दिखता

public class MyType : BaseClass<MyType, ConcreteSourceType, ConcreteEventArgsType> 
{ 
    protected MyType() : base("SomeName") 
    { 

    } 
} 
+0

एक नज़र के रूप में अच्छा है यहां http://stackoverflow.com/questions/893423/how-do-create-a-dynamic-class-in-c-sharp-4 –

+0

वास्तव में सहायक नहीं है या क्या मुझे कुछ याद आया? मैं बेसक्लास से उत्तराधिकारी बनना चाहता हूं और इसे मूल आधार निर्माता कहता हूं जिसमें तर्क है। – SACO

+0

इस लिंक को भी आजमाएं http://blogs.msdn.com/b/cburrows/archive/2009/04/22/dynamic-base-classes-in-c-4.aspx –

उत्तर

10

मुझे लगता है कि समस्या यह है कि है आप खुले जेनेरिक प्रकार GenericType<GT, TEventSource, TEventArgs> के निर्माता को कॉल करने का प्रयास कर रहे हैं, लेकिन आपको बंद प्रकार BaseClass<MyType, ConcreteSourceType, ConcreteEventArgsType> के निर्माता को कॉल करने की आवश्यकता है। का हल आसान लगता है:

var baseCtor = baseType.GetConstructor(
    BindingFlags.NonPublic | BindingFlags.Instance, null, 
    new[] { typeof(string) }, null); 

समस्या यह है कि यह काम नहीं करता है और NotSupportedException फेंकता है। इसलिए, ऐसा लगता है कि एक सामान्य प्रकार का निर्माता है, जहां पैरामीटर में से एक TypeBuilder अखरोट समर्थित है।

इसके कारण, मुझे लगता है कि आप जो चाहते हैं वह प्रतिबिंब का उपयोग करके संभव नहीं है। स्वीकार करें, जब तक कि इसके आसपास काम करने के लिए कुछ हैक न हो।

संपादित करें: ए-एचए! मुझे प्रतिबिंब में गहराई से डुबोना पड़ा। प्रतिबिंब में प्रवेश (हालांकि प्रलेखन में सही जगह को देखकर भी काम किया होगा), लेकिन मुझे यह पता चला: इसके लिए बिल्कुल एक विशेष विधि है: the static TypeBuilder.GetConstructor()। तो यह काम करना चाहिए:

var baseNonGenericCtor = baseNotGenericType.GetConstructor(
    BindingFlags.NonPublic | BindingFlags.Instance, null, 
    new[] { typeof(string) }, null); 
var baseCtor = TypeBuilder.GetConstructor(baseType, baseNonGenericCtor); 
+0

तो मैं एक हैक देखने की उम्मीद कर रहा हूं :) – SACO

+0

असल में, यह संभव है और यह बिल्कुल एक हैक नहीं है, संपादन देखें। – svick

+0

बीटीडब्लू, इस तरह के प्रश्न जो मुझे कुछ नया सीखने के लिए सबसे अच्छे हैं। – svick

3

यह करने के लिए एक सरल विधानसभा में अपने अमूर्त और व्युत्पन्न वर्ग तक संकलित करने के लिए, फिर "Reflection.Emit" भाषा एक ऐड के रूप में उपलब्ध का उपयोग कर परावर्तक में उन्हें खोलने होगा सबसे आसान तरीका से:

http://reflectoraddins.codeplex.com/

Reflector: Reflection.Emit language

हां, यह के रूप में यह लग रहा है :)

+0

क्या आप वाकई इस विशिष्ट मामले में काम करेंगे? – svick

+0

यदि आपकी वांछित कक्षा परिभाषा वैध सी # है और संकलित होगी, तो हाँ। – x0n

+0

ठीक है, इस मामले में उत्पन्न कोड बहुत अधिक समझ में नहीं आता है और ओपी की मदद नहीं करेगा। ऐसा इसलिए है क्योंकि यह 'टाइपोफ (माईटाइप)' का उपयोग करता है, जो उस प्रकार के निर्माण के दौरान समझ में नहीं आता है। और इसके बजाय 'टाइपबिल्डर' का उपयोग करके 'NotSupportedException' की ओर अग्रसर होगा। – svick

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