2012-09-14 9 views
7

अपनी खुद की भाषा के लिए एक कंपाइलर बनाने के साथ खिलौना, मैं प्रतिबिंब का उपयोग करके कुछ एमएसआईएल कोड उत्पन्न करने की कोशिश कर रहा हूं। फ्रेमवर्क स्वीकार करें। जब मैं स्थानीय चर घोषित करता हूं तो int का उपयोग करते समय यह ठीक काम करता है। हालांकि, जब मैं एक प्रकार के स्थानीय चर घोषित करना चाहता हूं, मैंने अभी तक संकलित नहीं किया है, तो मुझे DeclareLocal() तर्क के रूप में Type लेता है क्योंकि मुझे परेशानी हो रही है। यह मेरा uncompiled वर्ग है, कहते हैं कि A, अभी भीILGenerator.DeclareLocal() एक वर्ग का एक प्रकार लेता है जिसे अभी तक संकलित नहीं किया गया है

class A { 
    void M() { B b = new B(); } 
} 
class B 
    void M() { A a = new A(); } 
} 
+0

इससे क्या मदद मिलेगी? –

+1

@phoog: वह शायद किसी के लिए अपना काम करने का इंतजार कर सकता है, तो .. –

+0

मैं वास्तव में सी # नहीं कर रहा हूं .. यह सर्कुलर निर्भरता का एक उदाहरण था –

उत्तर

7

प्राथमिक अंतर्दृष्टि तुम यहाँ की जरूरत है कि TypeBuilder है

assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemName, AssemblyBuilderAccess.RunAndSave); 
module = assemblyBuilder.DefineDynamicModule(Filename); 
module.DefineType(name, TypeAttributes.Public | TypeAttributes.Class) 

तो का उपयोग कर कैसे मैंने कभी निम्नलिखित कार्यक्रम को संकलित करने में सक्षम हो जाएगा परिभाषित करने की आवश्यकता Type से निकला है। इसलिए, भले ही आपने अभी तक एक प्रकार को अंतिम रूप दिया नहीं है (CreateType() पर कॉल करके), आप इसे किसी अन्य प्रकार में स्थानीय चर घोषित करने के लिए उपयोग कर सकते हैं।

एक और बाधा मुझे सामना करना पड़ा है कि एक अधूरा TypeBuilder पर GetConstructor() काम नहीं करता है (यह एक अपवाद फेंकता है)। लेकिन यदि आप स्पष्ट रूप से डिफ़ॉल्ट कन्स्ट्रक्टर बनाते हैं, तो आप इसे ConstructorBuilder के माध्यम से कॉल कर सकते हैं।

static void Main() 
{ 
    var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
     new AssemblyName("foo"), AssemblyBuilderAccess.RunAndSave); 
    var module = assemblyBuilder.DefineDynamicModule("foo.dll"); 
    var aType = module.DefineType(
     "A", TypeAttributes.Public | TypeAttributes.Class); 
    var bType = module.DefineType(
     "B", TypeAttributes.Public | TypeAttributes.Class); 
    var aCtor = aType.DefineDefaultConstructor(MethodAttributes.Public); 
    var bCtor = bType.DefineDefaultConstructor(MethodAttributes.Public); 
    CreateMethodM(aType, bType, bCtor); 
    CreateMethodM(bType, aType, aCtor); 
    aType.CreateType(); 
    bType.CreateType(); 
    assemblyBuilder.Save("foo.dll"); 
} 

static void CreateMethodM(
    TypeBuilder thisType, Type otherType, ConstructorInfo otherCtor) 
{ 
    var method = thisType.DefineMethod(
     "M", MethodAttributes.Private, typeof(void), Type.EmptyTypes); 
    var il = method.GetILGenerator(); 
    var local = il.DeclareLocal(otherType); 
    il.Emit(OpCodes.Newobj, otherCtor); 
    il.Emit(OpCodes.Stloc, local); 
    il.Emit(OpCodes.Ret); 
} 
+1

अरग! मेरा समाधान तुम्हारा बहुत करीब है! मुझे बस "टी" –

+2

'डीक्लियरिंग टाइप' की बजाय "टी। डीक्लेरिंग टाइप" को कॉल करने के लिए अंधा कर दिया गया था, यह कुछ अलग है, यह इस प्रकार का प्रकार घोषित किया गया है, उदाहरण के लिए जब यह एक नेस्टेड प्रकार है। – svick

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