2009-05-30 9 views
16

मैं एक प्रश्न पूछने जा रहा हूं जो अजीब लग सकता है।रनटाइम के दौरान एक नया प्रकार बनाने का कोई तरीका है?

रनटाइम के दौरान एक नई कक्षा बनाने का कोई तरीका है? या कम से कम, एक मौजूदा वर्ग में एक नई संपत्ति जोड़ें।

मेरा मतलब है कि एक वर्ग बनाना जो अस्तित्व में नहीं है और मौजूदा वर्ग का उदाहरण नहीं है। मैं बाद में इस वर्ग को लोड करने और उपयोग करने के लिए उपयोग प्रतिबिंबों पर उपयोग कर सकता था।

उत्तर

21

किसी मौजूदा प्रकार में कोई संपत्ति जोड़ना संभव नहीं है, लेकिन आप Reflection.Emit का उपयोग कर रनटाइम पर एक नया प्रकार बना सकते हैं। यह बहुत जटिल सामान है, और यह कुछ इस तरह चला जाता है:

AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(
     assemblyName , AssemblyBuilderAccess.Run, assemblyAttributes); 
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("ModuleName"); 
TypeBuilder typeBuilder = moduleBuilder.DefineType(
     "MyNamespace.TypeName" , TypeAttributes.Public); 

typeBuilder.DefineDefaultConstructor(MethodAttributes.Public); 

// Add a method 
newMethod = typeBuilder.DefineMethod("MethodName" , MethodAttributes.Public); 

ILGenerator ilGen = newMethod.GetILGenerator(); 

// Create IL code for the method 
ilGen.Emit(...); 

// ... 

// Create the type itself 
Type newType = typeBuilder.CreateType(); 

इस कोड को सिर्फ एक नमूना है। इसमें त्रुटियां हो सकती हैं।

आप System.CodeDom का उपयोग कर रनटाइम पर सी # स्रोत कोड संकलित करके कक्षाएं भी उत्पन्न कर सकते हैं, लेकिन मुझे इसके बारे में बहुत कुछ पता नहीं है।

+0

क्षमा मीटर rwwilden में चिह्नित किए गए यह जवाब के रूप में है के लिए देख रहा था के बाद से इस सवाल का जवाब और अधिक प्रयास से बनाया गया था (यू के दोनों सोचा है एक ही समाधान intorduced) – user88637

+0

कोई समस्या नहीं है। मैं मानता हूं कि यह मेरे अपने उत्तर से थोड़ा अधिक विस्तृत है। –

4

System.Reflection.Emit नामस्थान पर एक नज़र डालें। मैंने इसे कभी भी इस्तेमाल नहीं किया है लेकिन इस नामस्थान में कक्षाओं का उपयोग आईएल (इंटरमीडिएट भाषा) उत्पन्न करने के लिए किया जा सकता है।

+0

धन्यवाद, यह वास्तव में क्या मैं – user88637

3

आप System.CodeDom नामस्थान पर एक नज़र डाल सकते हैं।

.नेट फ्रेमवर्क एक तंत्र संहिता दस्तावेज़ ऑब्जेक्ट मॉडल (CodeDOM) कि प्रोग्राम हैं जो एक से अधिक प्रोग्रामिंग भाषाओं में स्रोत कोड उत्पन्न करने के लिए स्रोत कोड का उत्सर्जन के डेवलपर्स के लिए सक्षम बनाता बुलाया शामिल हैं: पृष्ठों में से एक वहां से जुड़ा हुआ के अनुसार रेंडर करने के लिए कोड का प्रतिनिधित्व करने वाले एक मॉडल पर आधारित रन टाइम।

मैं इस में एक विशेषज्ञ नहीं हूं, मुझे बस अपनी दीवार पर अपने .NET Framework पोस्टर पर इसे देखकर याद आया। :)

संपादित करें: इस उत्तर को लिखने के बाद से, मैंने सिस्टम के साथ खेला है। कोडडॉम थोड़ा सा। मैंने blog post लिखा है जो कुछ बुनियादी कोडडॉम का उपयोग करता है जो उन लोगों की मदद कर सकता है जो इसके साथ शुरुआत करना चाहते हैं।

5

यह एक अजीब सवाल नहीं है - कुछ मामलों में यह बहुत उपयोगी हो सकता है। उदाहरण के लिए मैं कभी कभी प्रदर्शन परीक्षणों के लिए इस तकनीक का उपयोग करें:

public static Type[] DynamicTypes; 

public void CreateObjects() 
{ 
    var codeNamespace = new CodeNamespace("DynamicClasses"); 
    codeNamespace.Imports.Add(new CodeNamespaceImport("System")); 
    codeNamespace.Imports.Add(new CodeNamespaceImport("System.ComponentModel")); 

    for(var i = 0; i < 2000; i++) 
    { 
    var classToCreate = new CodeTypeDeclaration("DynamicClass_" + i) 
    { 
     TypeAttributes = TypeAttributes.Public 
    }; 
    var codeConstructor1 = new CodeConstructor 
    { 
     Attributes = MemberAttributes.Public 
    }; 
    classToCreate.Members.Add(codeConstructor1); 

    codeNamespace.Types.Add(classToCreate); 
    } 

    var codeCompileUnit = new CodeCompileUnit(); 
    codeCompileUnit.Namespaces.Add(codeNamespace); 

    var compilerParameters = new CompilerParameters 
    { 
    GenerateInMemory = true, 
    IncludeDebugInformation = true, 
    TreatWarningsAsErrors = true, 
    WarningLevel = 4 
    }; 
    compilerParameters.ReferencedAssemblies.Add("System.dll"); 

    var compilerResults = new CSharpCodeProvider().CompileAssemblyFromDom(compilerParameters, codeCompileUnit); 

    if(compilerResults == null) 
    { 
    throw new InvalidOperationException("ClassCompiler did not return results."); 
    } 
    if(compilerResults.Errors.HasErrors) 
    { 
    var errors = string.Empty; 
    foreach(CompilerError compilerError in compilerResults.Errors) 
    { 
     errors += compilerError.ErrorText + "\n"; 
    } 
    Debug.Fail(errors); 
    throw new InvalidOperationException("Errors while compiling the dynamic classes:\n" + errors); 
    } 

    var dynamicAssembly = compilerResults.CompiledAssembly; 
    DynamicTypes = dynamicAssembly.GetExportedTypes(); 
} 
संबंधित मुद्दे