编译在运行时code,加载到当前的AppDomain但Type.GetType不能看到它能看、到它、加载、code

2023-09-03 05:52:43 作者:梦醒心未醒

林编译一些code运行时再加载程序集到当前的AppDomain,但是当我再尝试做Type.GetType它不能找到的类型...

下面是我如何编译code ...

 公共静态大会编译code(字符串code)
    {
        Microsoft.CSharp.CSharp codeProvider商=新CSHARP codeProvider();
        I codeCompiler编译器= provider.CreateCompiler();
        CompilerParameters compilerparams =新CompilerParameters();
        compilerparams.GenerateExecutable = FALSE;
        compilerparams.GenerateInMemory = FALSE;

        的foreach(在AppDomain.CurrentDomain.GetAssemblies装配组件())
        {
            尝试
            {
                字符串位置= assembly.Location;
                如果(!String.IsNullOrEmpty(位置))
                {
                    compilerparams.ReferencedAssemblies.Add(位置);
                }
            }
            赶上(NotSupportedException异常)
            {
                //发生这种情况的动态程序集,所以就忽略它。
            }
        }
        CompilerResults结果=
           compiler.CompileAssemblyFromSource(compilerparams,code);
        如果(results.Errors.HasErrors)
        {
            StringBuilder的错误=新的StringBuilder(编译器错误:\ r \ N);
            的foreach(在results.Errors CompilerError错误)
            {
                errors.AppendFormat(行{0},{1} \ T:{2} \ N,
                       error.Line,error.Column,error.ErrorText);
            }
            抛出新的异常(errors.ToString());
        }
        其他
        {
            AppDomain.CurrentDomain.Load(results.CompiledAssembly.GetName());
            返回results.CompiledAssembly;
        }
    }
 

该位从编译的程序集得到的类型后就好了,它似乎失败并不能够使用Type.GetType它来寻找......

 大会ASSEM =运行codeCompiler.Compile code(code);
字符串的typeName =
      的String.Format(Peverel.AppFramework.Web.Gen code.ObjectDataSourceProxy_ {0},
        safeTypeName);



类型t = assem.GetType(typeName的); //这只是正常..
键入doesntWork = Type.GetType(t.AssemblyQualifiedName);
键入doesntWork2 = Type.GetType(t.Name);



....
 
vs code 终端突然运行不了

解决方案

找到这个的code,以确保无论你如何加载程序集它总是可以从Type.GetType。不错位

我的班级编制code到当前的AppDomain现在看起来像:

 公共静态Runtime类codeCompiler
{
    私有静态挥发字典<字符串,大会>缓存=新字典<字符串,装配及GT;();
    私有静态对象SyncRoot上=新的对象();
    静态字典<字符串,大会>组件=新字典<字符串,装配及GT;();
    静态运行codeCompiler()
    {
        AppDomain.CurrentDomain.AssemblyLoad + =(发件人,E)=>
        {
            组件[e.LoadedAssembly.FullName] = e.LoadedAssembly;
        };
        AppDomain.CurrentDomain.AssemblyResolve + =(发件人,E)=>
        {
            装配装配= NULL;
            assemblies.TryGetValue(e.Name,出组装);
            返回组装;
        };

    }


    公共静态大会编译code(字符串code)
    {

        Microsoft.CSharp.CSharp codeProvider商=新CSHARP codeProvider();
        I codeCompiler编译器= provider.CreateCompiler();
        CompilerParameters compilerparams =新CompilerParameters();
        compilerparams.GenerateExecutable = FALSE;
        compilerparams.GenerateInMemory = FALSE;



        的foreach(在AppDomain.CurrentDomain.GetAssemblies装配组件())
        {
            尝试
            {
                字符串位置= assembly.Location;
                如果(!String.IsNullOrEmpty(位置))
                {
                    compilerparams.ReferencedAssemblies.Add(位置);
                }
            }
            赶上(NotSupportedException异常)
            {
                //发生这种情况的动态程序集,所以就忽略它。
            }
        }


        CompilerResults结果=
           compiler.CompileAssemblyFromSource(compilerparams,code);
        如果(results.Errors.HasErrors)
        {
            StringBuilder的错误=新的StringBuilder(编译器错误:\ r \ N);
            的foreach(在results.Errors CompilerError错误)
            {
                errors.AppendFormat(行{0},{1} \ T:{2} \ N,
                       error.Line,error.Column,error.ErrorText);
            }
            抛出新的异常(errors.ToString());
        }
        其他
        {

            AppDomain.CurrentDomain.Load(results.CompiledAssembly.GetName());
            返回results.CompiledAssembly;
        }

    }

    公共静态大会编译codeOrGetFromCache(字符串code,字符串键)
    {
        布尔存在= cache.ContainsKey(密钥);

        如果(!存在)
        {

            锁定(SyncRoot上)
            {
                存在= cache.ContainsKey(密钥);

                如果(!存在)
                {
                    cache.Add(键,编译code(code));
                }
            }
        }

        返回高速缓存[重点]
    }


}
 

Im compiling some code at runtime then loading the assembly into the current appdomain, however when i then try to do Type.GetType it cant find the type...

Here is how i compile the code...

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;
        }
    }

This bit fails after getting the type from the compiled assembly just fine, it does not seem to be able to find it using Type.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);



....

解决方案

Found this nice bit of code that ensures no matter how you load your assembly it is always available from Type.GetType.

My class for compiling code into the current appdomain now looks like :

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];
    }


}