2010-06-11 10 views
5

मैं रनटाइम पर कुछ कोड संकलित करता हूं और फिर असेंबली को वर्तमान एपडोमेन में लोड करता हूं, हालांकि जब मैं टाइप टाइप करता हूं तो टाइप टाइप करें। ..रनटाइम पर कोड संकलित करना, वर्तमान एपडोमेन में लोड करना, लेकिन Type.GetType इसे देख नहीं सकता

यहाँ है कैसे मैं कोड संकलन ...

public static Assembly CompileCode(string code) 
    { 
     Microsoft.CSharp.CSharpCodeProvider provider = new CSharpCodeProvider(); 
     ICodeCompiler compiler = provider.CreateCompiler(); 
     CompilerParameters compilerparams = new CompilerParameters(); 
     compilerparams.GenerateExecutable = false; 
     compilerparams.GenerateInMemory = false; 

     foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) 
     { 
      try 
      { 
       string location = assembly.Location; 
       if (!String.IsNullOrEmpty(location)) 
       { 
        compilerparams.ReferencedAssemblies.Add(location); 
       } 
      } 
      catch (NotSupportedException) 
      { 
       // this happens for dynamic assemblies, so just ignore it. 
      } 
     } 
     CompilerResults results = 
      compiler.CompileAssemblyFromSource(compilerparams, code); 
     if (results.Errors.HasErrors) 
     { 
      StringBuilder errors = new StringBuilder("Compiler Errors :\r\n"); 
      foreach (CompilerError error in results.Errors) 
      { 
       errors.AppendFormat("Line {0},{1}\t: {2}\n", 
         error.Line, error.Column, error.ErrorText); 
      } 
      throw new Exception(errors.ToString()); 
     } 
     else 
     { 
      AppDomain.CurrentDomain.Load(results.CompiledAssembly.GetName()); 
      return results.CompiledAssembly; 
     } 
    } 

इस बिट संकलित विधानसभा से टाइप हो रही ठीक बाद विफल रहता है, यह प्रकार का उपयोग कर इसे खोजने के लिए सक्षम होने के लिए प्रतीत नहीं होता। GetType ....

Assembly assem = RuntimeCodeCompiler.CompileCode(code); 
string typeName = 
     String.Format("Peverel.AppFramework.Web.GenCode.ObjectDataSourceProxy_{0}", 
     safeTypeName); 



Type t = assem.GetType(typeName); //This works just fine.. 
Type doesntWork = Type.GetType(t.AssemblyQualifiedName); 
Type doesntWork2 = Type.GetType(t.Name); 



.... 
+0

मैं सफलतापूर्वक विधानसभा करते हैं और ऐसा एप्लिकेशन डोमेन कि Type.GetType कि विधानसभा में प्रकार मिलेगा में लोड करने के बाद उम्मीद करेंगे। । –

उत्तर

8

मिला this कोड का अच्छा बिट जो सुनिश्चित करता है कि आप अपनी असेंबली को कैसे लोड करते हैं, यह हमेशा Type.GetType से उपलब्ध है।

वर्तमान appdomain में कोड संकलन के लिए मेरी कक्षा अब लगता है कि:

public static class RuntimeCodeCompiler 
{ 
    private static volatile Dictionary<string, Assembly> cache = new Dictionary<string, Assembly>(); 
    private static object syncRoot = new object(); 
    static Dictionary<string, Assembly> assemblies = new Dictionary<string, Assembly>(); 
    static RuntimeCodeCompiler() 
    { 
     AppDomain.CurrentDomain.AssemblyLoad += (sender, e) => 
     { 
      assemblies[e.LoadedAssembly.FullName] = e.LoadedAssembly; 
     }; 
     AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => 
     { 
      Assembly assembly = null; 
      assemblies.TryGetValue(e.Name, out assembly); 
      return assembly; 
     }; 

    } 


    public static Assembly CompileCode(string code) 
    { 

     Microsoft.CSharp.CSharpCodeProvider provider = new CSharpCodeProvider(); 
     ICodeCompiler compiler = provider.CreateCompiler(); 
     CompilerParameters compilerparams = new CompilerParameters(); 
     compilerparams.GenerateExecutable = false; 
     compilerparams.GenerateInMemory = false; 



     foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) 
     { 
      try 
      { 
       string location = assembly.Location; 
       if (!String.IsNullOrEmpty(location)) 
       { 
        compilerparams.ReferencedAssemblies.Add(location); 
       } 
      } 
      catch (NotSupportedException) 
      { 
       // this happens for dynamic assemblies, so just ignore it. 
      } 
     } 


     CompilerResults results = 
      compiler.CompileAssemblyFromSource(compilerparams, code); 
     if (results.Errors.HasErrors) 
     { 
      StringBuilder errors = new StringBuilder("Compiler Errors :\r\n"); 
      foreach (CompilerError error in results.Errors) 
      { 
       errors.AppendFormat("Line {0},{1}\t: {2}\n", 
         error.Line, error.Column, error.ErrorText); 
      } 
      throw new Exception(errors.ToString()); 
     } 
     else 
     { 

      AppDomain.CurrentDomain.Load(results.CompiledAssembly.GetName()); 
      return results.CompiledAssembly; 
     } 

    } 

    public static Assembly CompileCodeOrGetFromCache(string code, string key) 
    { 
     bool exists = cache.ContainsKey(key); 

     if (!exists) 
     { 

      lock (syncRoot) 
      { 
       exists = cache.ContainsKey(key); 

       if (!exists) 
       { 
        cache.Add(key, CompileCode(code)); 
       } 
      } 
     } 

     return cache[key]; 
    } 


} 
+0

मैं अब इस विषय पर शोध कर रहा हूं और आपके कोड, @ रिचर्ड में आया हूं, लेकिन मुझे पूरा यकीन नहीं है कैश तंत्र कैसे काम करता है। क्या आपको याद है/क्या आप समझा सकते हैं? बहुत बहुत धन्यवाद। – Jack

-1

आपको असेंबली लोडिंग, रिज़ॉल्यूशन टाइप करने के बारे में कुछ और पढ़ना चाहिए ... मुझे नहीं पता कि आपका कोड बिल्कुल क्यों काम करता है, लेकिन मुझे लगता है कि आपको निम्न समस्या है:

आप असेंबली संकलित करते हैं और फिर आप असेंबली लोड करने के लिए AppDomain.CurrentDomain.Load को कॉल करते हैं। लेकिन आप जिस असेंबली को अभी लोड कर चुके हैं उसे वापस नहीं लौटते हैं। आप संकलन परिणाम से असेंबली वापस करते हैं। अब आपके पास एक ही असेंबली के दो उदाहरण हैं और आपके पास उस विधानसभा से प्रत्येक प्रकार का दो बार है। इन जोड़े के समान नाम हैं, लेकिन वे एक ही प्रकार के नहीं हैं!

+0

मैं विधानसभा AppDomain.CurrentDomain.GetAssemblies() मैं तो AppDomain.CurrentDomain.GetAssemblies() [50] .GetTypes() हालांकि मुझे लगता है कि dynamicalyy लोड प्रकार नहीं कर सकते हैं के साथ प्रकार देख सकते हैं के साथ भरी हुई देख सकते हैं Type.GetTypeका उपयोग करके पाएं देखें http://bytes.com/topic/c-sharp/answers/428836-reflection-type-gettype –

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