在运行时编译代码,加载到当前appdomain但Type.GetType不能看到它 [英] Compiling code at runtime, loading into current appdomain but Type.GetType cant see it

查看:146
本文介绍了在运行时编译代码,加载到当前appdomain但Type.GetType不能看到它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Im在运行时编译一些代码,然后将程序集加载到当前的appdomain,然而当我然后尝试做Type.GetType它找不到类型...

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

此位在从编译程序集中获取类型后失败只是很好,它似乎不能找到它使用Type.GetType ....

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



....


推荐答案

找到

我的类用于编译代码到当前appdomain现在看起来像:

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


}

这篇关于在运行时编译代码,加载到当前appdomain但Type.GetType不能看到它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆