在运行时多次加载 Roslyn 编译的 DLL
Load with Roslyn compiled DLL at runtime multiple times
目前我正在运行时编译和加载程序集。该程序集始终包含相同的命名空间和 类。当我这样做时
在同一个应用程序实例中多次,在创建程序集中 类 的新实例时,总是会使用 最新的 程序集吗?或者这不能保证?
你正在创造你想要创造的东西。不过,这可能是也可能不是您想要创建的内容。
很可能,您的程序集没有特定名称,而是一个随机的唯一名称 - 在这种情况下,类型完全不同,就 .NET 而言只是偶然相似。来自两个不同编译的类型是完全不相关的,并且不兼容。当您通过动态程序集外部定义的接口访问它们时,这可能会或可能不会成为问题,具体取决于您使用这些类型的方式。
如果添加程序集名称,情况会变得有点复杂。你不能加载同一个程序集两次(旧的不会被新的替换),所以你需要改变版本。然而,同一个程序集的两个版本不能加载到同一个应用程序域中(除了 "fun" 和 AssemblyResolve
等 - 但要做到这一点非常棘手)。第二个程序集将无法加载。
最后,您尝试实例化的 Type
是您 做 实例化的那个(除非使用绑定重定向,这是额外的乐趣: )。如果您的某些代码保留了之前编译的 Type
,那么它将创建的就是它。
如果你的问题是我是否在 AppDomain 中加载程序集
Assembly a1=Assembly.Load(Array of Assembly);
然后使用 roslyn 更改代码,如 class 名称并创建项目的新程序集并再次加载它
Assembly a2 =Assembly.Load(Array of Assembly);
现在 a2 加载到 CurrentDomain 了吗?
我的回答是 .a1 现在不在 CurrentDomain 中。
你可以测试一下。
因此,要使用新程序集,您必须使用以下解决方案。
您需要在另一个 AppDomain 中加载此程序集,每次您都可以卸载此 AppDomain 并重新创建它并再次加载程序集
首先创建一个 class,CurrentDomain 会将其实例加载到另一个 AppDomain class 的这个对象必须加载您的程序集及其对第二个 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);
目前我正在运行时编译和加载程序集。该程序集始终包含相同的命名空间和 类。当我这样做时 在同一个应用程序实例中多次,在创建程序集中 类 的新实例时,总是会使用 最新的 程序集吗?或者这不能保证?
你正在创造你想要创造的东西。不过,这可能是也可能不是您想要创建的内容。
很可能,您的程序集没有特定名称,而是一个随机的唯一名称 - 在这种情况下,类型完全不同,就 .NET 而言只是偶然相似。来自两个不同编译的类型是完全不相关的,并且不兼容。当您通过动态程序集外部定义的接口访问它们时,这可能会或可能不会成为问题,具体取决于您使用这些类型的方式。
如果添加程序集名称,情况会变得有点复杂。你不能加载同一个程序集两次(旧的不会被新的替换),所以你需要改变版本。然而,同一个程序集的两个版本不能加载到同一个应用程序域中(除了 "fun" 和 AssemblyResolve
等 - 但要做到这一点非常棘手)。第二个程序集将无法加载。
最后,您尝试实例化的 Type
是您 做 实例化的那个(除非使用绑定重定向,这是额外的乐趣: )。如果您的某些代码保留了之前编译的 Type
,那么它将创建的就是它。
如果你的问题是我是否在 AppDomain 中加载程序集
Assembly a1=Assembly.Load(Array of Assembly);
然后使用 roslyn 更改代码,如 class 名称并创建项目的新程序集并再次加载它
Assembly a2 =Assembly.Load(Array of Assembly);
现在 a2 加载到 CurrentDomain 了吗? 我的回答是 .a1 现在不在 CurrentDomain 中。
你可以测试一下。
因此,要使用新程序集,您必须使用以下解决方案。
您需要在另一个 AppDomain 中加载此程序集,每次您都可以卸载此 AppDomain 并重新创建它并再次加载程序集
首先创建一个 class,CurrentDomain 会将其实例加载到另一个 AppDomain class 的这个对象必须加载您的程序集及其对第二个 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);