[英]Assembly.LoadFrom() or Assembly.Load() being able to delete file
我的目標:我正在編寫一個vsix(Visual Studio擴展),我想在其中編譯項目,然后加載生成的.dll並通過反射對其進行檢查。 由於代碼的編寫方式,我無法使用ReflectionOnlyLoad()
。 如果我只是簡單地執行Assembly.Load
則文件將被鎖定,直到用戶重新啟動整個IDE。
我試圖根據我在網上找到的樣本來設置單獨的AppDomain。
要點是:1.我創建了一個Proxy類,該類將AppDomain
實例之間的數據:
internal class AppDomainProxy : MarshalByRefObject
{
public Assembly GetAssembly(string assemblyPath)
{
return Assembly.LoadFile(assemblyPath);
}
}
然后,我創建一個實例:
var domaininfo = new AppDomainSetup { ApplicationBase = System.Environment.CurrentDirectory, ShadowCopyDirectories = "true", ShadowCopyFiles = "true", LoaderOptimization = LoaderOptimization.MultiDomainHost };
var adevidence = System.AppDomain.CurrentDomain.Evidence;
var domain = System.AppDomain.CreateDomain("reflection", adevidence, domaininfo);
var proxyType = new AppDomainProxy().GetType();
var proxyInstance = (AppDomainProxy)domain.CreateInstanceFromAndUnwrap(proxyType.Assembly.Location, proxyType.FullName);
var loadedAssembly = (proxyInstance as AppDomainProxy).GetAssembly(this._assemblyLocation);
這無法將我的透明代理轉換為我的AppDomainProxy
類型。 要解決此問題,可以輕松地提供一個裝配體分解器,如下所示:
this.domain.AssemblyResolve += CurrentDomainOnAssemblyResolve;
private Assembly CurrentDomainOnAssemblyResolve(object sender, ResolveEventArgs args)
{
var loadedAssemblies = System.AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in loadedAssemblies)
{
if (assembly.FullName == args.Name)
{
return assembly;
}
}
return null;
}
這個工作正常,我的代理服務器已投放。 但是,當我調用我的方法時, CurrentDomainOnAssemblyResolve
再次被調用,向我暗示Assembly
屬性實際上不是可序列化的,因此.net只是試圖在原始端加載Assembly,因此導致與Assembly.Load
相同的問題。 。 這很容易看到,因為像Microsoft這樣的簡單示例就return AppDomain.Current.FriendlyName;
工作很好。
更新作為一種解決方法,我只是移動了需要Assembly在另一端(在域內)運行的代碼,然后將返回的字符串進行整理。 但是,我將保持開放的狀態,因為我想知道實際問題是否有解決方案。
好吧,當然,您需要將需要與程序集一起使用的代碼移動到單獨的AppDomain
。 不需要任何魔術-如果您需要使用引用的程序集中的類型,則需要加載該程序集。
跨AppDomain
邊界(和其他遠程處理方案)封送對象的主要方法有兩種:要么制作對象的副本,要么封送所有方法調用。 兩者都是非常棘手的-必須確保不要泄漏引用程序集中的類型,否則需要將其加載到兩個域中。 在您的情況下,您不能編組方法調用,因為Assembly
不是 (也不能是) MarshalByRefObject
您的代理必須返回真實的Assembly
對象,並且不能創建編組代理。
為了獲得適當的隔離,您必須避免泄漏您不想共享的程序集中的任何類型,以及可能暴露其中任何類型的非編組類型。 如果可以承受的話,這通常意味着堅持使用共享庫中的原語和類型。 保持良好的緊密接口,並盡量避免過度利用“自動”編組功能-將自動代理返回到復雜對象很方便,但會使理解接口范圍變得更加困難。 對象是否具有從非共享程序集中返回類型的方法? 太糟糕了,您也需要將其加載到您的域中。
通常,使用實際可互操作的多個AppDomain(以及相關的.NET遠程處理)是一個巨大的痛苦。 它很復雜,容易出錯,而且很難正確解決。 您可以閱讀有關該主題的整本書。 有一個原因為什么不再推薦使用它們-為什么PCL不支持它們(並且很長一段時間以來,Mono不支持它們)。 它們仍然有用嗎? 是啊。 軟件隔離具有非常好的好處。 但是您需要非常小心,不要把事情弄糟:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.