在运行时多次加载 Roslyn 编译的 DLL
Posted
技术标签:
【中文标题】在运行时多次加载 Roslyn 编译的 DLL【英文标题】:Load with Roslyn compiled DLL at runtime multiple times 【发布时间】:2016-05-10 06:17:53 【问题描述】:目前我正在运行时编译和加载程序集。程序集始终包含相同的命名空间和类。当我这样做时 在同一个应用程序实例中多次,在创建程序集中的类的新实例时,总是会使用 最新 程序集吗?还是不能保证?
【问题讨论】:
【参考方案1】:你正在创造你想要创造的东西。不过,这可能是也可能不是您想要创建的。
很可能,您的程序集没有特定名称,而是随机的唯一名称 - 在这种情况下,类型是完全不同的,并且就 .NET 而言只是偶然相似。来自两个不同编译的类型完全不相关,并且不兼容。当您通过在动态程序集之外定义的接口访问它们时,这可能会或可能不会出现问题,具体取决于您使用这些类型的准确程度。
如果添加程序集名称,情况会变得更复杂一些。您不能两次加载相同的程序集(旧的不会被新的替换),因此您需要更改版本。但是,不能在同一个应用程序域中加载同一个程序集的两个版本(除非用AssemblyResolve
等做“有趣” - 但这很难做到正确)。第二个程序集将无法加载。
最后,您尝试实例化的Type
是您做 实例化的那个(除非使用绑定重定向,这是额外的乐趣:P)。如果您的某些代码保留了先前编译中的 Type
,这就是它将创建的内容。
【讨论】:
感谢您的回答。所以我不应该遇到麻烦,因为在这种特定情况下,我不保存在 old 程序集中定义的类型的实例。非常感谢!是的,他们也没有名字,因为我在给他们名字的时候已经遇到了麻烦:) @BendEg 是的,应该可以正常工作。请注意,旧的程序集并没有被清理,所以如果您经常在同一个进程中进行编译,您可能希望将它们加载到不同的 AppDomain 中(您可以在不再有用时卸载域)。【参考方案2】:如果您的问题是我是否在 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);
【讨论】:
感谢您的回答。我从未使用过不同的 AppDomain。这是否允许主 AppDomain 和新创建的 AppDomain 之间轻松通信?谢谢 我在回答中说过。例如,您可以在程序集中获取 il 方法并将其返回给第一个 AppDomain。我将编辑答案 感谢您的详细回答和工作。我会试试这个然后回复你。 +2 如果我能... 我遇到了这个问题,所以我的代码可以工作。可能是打字不好。我用手机打字 更多关于AppDomains之间通信的信息msdn.microsoft.com/en-us/library/…以上是关于在运行时多次加载 Roslyn 编译的 DLL的主要内容,如果未能解决你的问题,请参考以下文章
如果我想在运行时部署时查看图像,要加载啥 dll,我真的需要哪个 vc dll?