簡體   English   中英

Assembly.LoadFrom()或Assembly.Load()能夠刪除文件

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM