【发布时间】:2016-05-10 06:17:53
【问题描述】:
目前我正在运行时编译和加载程序集。程序集始终包含相同的命名空间和类。当我这样做时 在同一个应用程序实例中多次,在创建程序集中的类的新实例时,总是会使用 最新 程序集吗?还是不能保证?
【问题讨论】:
标签: c# .net-assembly appdomain roslyn
目前我正在运行时编译和加载程序集。程序集始终包含相同的命名空间和类。当我这样做时 在同一个应用程序实例中多次,在创建程序集中的类的新实例时,总是会使用 最新 程序集吗?还是不能保证?
【问题讨论】:
标签: c# .net-assembly appdomain roslyn
你正在创造你想要创造的东西。不过,这可能是也可能不是您想要创建的。
很可能,您的程序集没有特定名称,而是随机的唯一名称 - 在这种情况下,类型是完全不同的,并且就 .NET 而言只是偶然相似。来自两个不同编译的类型完全不相关,并且不兼容。当您通过在动态程序集之外定义的接口访问它们时,这可能会或可能不会出现问题,具体取决于您使用这些类型的准确程度。
如果添加程序集名称,情况会变得更复杂一些。您不能两次加载相同的程序集(旧的不会被新的替换),因此您需要更改版本。但是,不能在同一个应用程序域中加载同一个程序集的两个版本(除非用AssemblyResolve 等做“有趣” - 但这很难做到正确)。第二个程序集将无法加载。
最后,您尝试实例化的Type 是您做 实例化的那个(除非使用绑定重定向,这是额外的乐趣:P)。如果您的某些代码保留了先前编译中的 Type,这就是它将创建的内容。
【讨论】:
如果您的问题是我是否在 AppDomain 中加载程序集
Assembly a1=Assembly.Load(Array of Assembly);
然后用 roslyn 类名称更改代码并创建项目的新程序集并再次加载它
Assembly a2 =Assembly.Load(Array of Assembly);
现在 a2 是否加载到 CurrentDomain 中? 我的答案是否定的。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);
【讨论】: