在运行时多次加载Roslyn编译的DLL

时间:2016-05-10 06:17:54

标签: c# .net-assembly appdomain roslyn

目前我正在运行时编译和加载程序集。程序集始终包含相同的名称空间和类。当我这样做的时候 在同一个应用程序实例中多次,在创建程序集中的类的新实例时,是否总是会使用最新的程序集?或者这不保证?

2 个答案:

答案 0 :(得分:1)

您正在创建您正在尝试创建的内容。但是,这可能是您希望创建的内容,也可能不是。

最有可能的是,你的程序集没有特定的名称,而是一个随机的唯一名称 - 在这种情况下,类型完全不同,只有.NET才会意外相似。两种不同编辑的类型完全不相关,并且不兼容。当您通过动态装配体外部定义的界面访问它们时,这可能会或可能不会成为问题,具体取决于您使用这些类型的具体程度。

如果添加程序集名称,情况会变得复杂一些。您无法加载同一个程序集两次(旧程序集不会被新程序集替换),因此您需要更改版本。但是,同一个程序集的两个版本无法在同一个应用程序域中加载(除非在执行" fun" with AssemblyResolve等等 - 但这样做是非常棘手的)。第二个组件将无法加载。

最后,您尝试实例化的Type是您实例化的那个(除非使用绑定重定向,这是额外的乐趣:P)。如果您的某些代码保留了之前编辑中的Type,那就是它要创建的内容。

答案 1 :(得分:1)

如果您的问题是我在AppDomain中加载程序集

Assembly a1=Assembly.Load(Array of Assembly);

然后使用类似名称的roslyn更改代码并创建项目的新程序集并再次加载

Assembly a2 =Assembly.Load(Array of Assembly);

现在是在CurrentDomain中加载了a2吗? 我的回答是没有.a1现在在CurrentDomain。

你可以测试它。

因此,对于使用新装配的工作,您必须使用以下解决方案。

您需要在另一个AppDomain中加载此程序集,并且每次卸载此AppDomain并再次创建它并再次加载程序集

首先创建一个类,CurrentDomain将该实例加载到另一个AppDomain,这个类的对象必须加载你的程序集及它对第二个AppDomain的依赖。

// you can create this class in another project and
// make assembly .because you need a copy of it in 
//folder that you set for ApplicationBase of second AppDomain
public class AssemblyLoader : MarshallByRefObject
{
    AssemblyLoader()
    {
         AppDomain.CurrentAppDomain.AssemblyResolve += LoaddependencyOfAssembly;
    }
public void LoaddependencyOfAssembly(object sender,)
{
    //load depdency of your assembly here
    // if you has replaced those dependencies  to folder that you set for ApplicationBase of second AppDomain doesn't need do anything here
}
public Assembly asm {get;set;}
public void LoadAssembly(MemoryStream ms)
{
     asm=  Assembly.Load(ms.ToArray());
}
}

在您要加载程序集的位置

AppDomainSetup s=new AppDomainSetup(){ApplicationBase="anotherFolderFromYourAppBinFoldr};
AppDomain ad= AppDomain.CreateDomain("name",AppDomain.CurrentDomain.Evidence,s);
Type t = typeof( AssemblyLoader);
 AssemblyLoader al = ( AssemblyLoader) ad.CreateInstanceAndUnwrap(t.Assembly.FullName,t.FullName);
// load assembly here by Stream or fileName
al.LoadAssembly(ms );
// now assembly loaded on ad 
// you can do your work with this assembly by al 
// for example  create a method in AssemblyLoader to 
// get il of methods with name of them 
//  Below IL is in CurrentDomain
//when compiler goes to GetIlAsByteArray you are in second AppDomain
byte[] IL = al.GetILAsByteArray("NameOfMethod");
//And unload second AppDomain 
 AppDomain.Unload(ad);