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

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

问题描述

林编译一些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);



....
 

解决方案

找到这个的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];
    }


}

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

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