第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

從字節(jié)數(shù)組加載時(shí)找不到AppDomain程序集

從字節(jié)數(shù)組加載時(shí)找不到AppDomain程序集

C#
紅顏莎娜 2021-05-18 15:15:20
請多多包涵,我花了30多個(gè)小時(shí)來嘗試完成這項(xiàng)工作,但沒有成功。在程序開始時(shí),我將程序集(dll)加載到字節(jié)數(shù)組中,然后將其刪除。_myBytes = File.ReadAllBytes(@"D:\Projects\AppDomainTest\plugin.dll");稍后在程序中,我創(chuàng)建一個(gè)新的Appdomain,加載字節(jié)數(shù)組并枚舉類型。var domain = AppDomain.CreateDomain("plugintest", null, null, null, false);domain.Load(_myBytes);foreach (var ass in domain.GetAssemblies()){    Console.WriteLine($"ass.FullName: {ass.FullName}");    Console.WriteLine(string.Join(Environment.NewLine, ass.GetTypes().ToList()));}類型正確列出:ass.FullName:插件,版本= 1.0.0.0,文化=中性,PublicKeyToken =空...插件測試...現(xiàn)在,我想在新的AppDomain中創(chuàng)建該類型的實(shí)例domain.CreateInstance("plugin", "Plugins.Test");導(dǎo)致此呼叫System.IO.FileNotFoundException,但我不知道為什么。當(dāng)我在下面的ProcessExplorer中.NET Assemblies -> Appdomain: plugintest查看時(shí),我看到該程序集已正確加載到新的appdomain中。我懷疑會(huì)發(fā)生異常,因?yàn)樵俅卧诖疟P上搜索了程序集。但是,為什么程序要再次加載它?如何使用從字節(jié)數(shù)組加載的程序集在新的appdomain中創(chuàng)建實(shí)例?
查看完整描述

3 回答

?
慕標(biāo)5832272

TA貢獻(xiàn)1966條經(jīng)驗(yàn) 獲得超4個(gè)贊

這里的主要問題是,您可以在執(zhí)行主appdomain中的代碼時(shí)實(shí)例化插件。


您需要做的是創(chuàng)建一個(gè)代理類型,該類型在已加載的程序集中定義,但在新的appdomain中實(shí)例化。在兩個(gè)應(yīng)用程序域中都未加載類型的程序集的情況下,您無法跨應(yīng)用程序域邊界傳遞類型。 例如,如果您想像上面那樣枚舉類型并打印到控制臺,則應(yīng)從在新應(yīng)用程序域中執(zhí)行的代碼執(zhí)行,而不要從在當(dāng)前應(yīng)用程序域中執(zhí)行的代碼執(zhí)行。


所以,讓我們創(chuàng)造我們的插件的代理,這樣會(huì)存在于你的主要組件,并負(fù)責(zé)執(zhí)行所有插件相關(guān)的代碼:


// Mark as MarshalByRefObject allows method calls to be proxied across app-domain boundaries

public class PluginRunner : MarshalByRefObject

{

    // make sure that we're loading the assembly into the correct app domain.

    public void LoadAssembly(byte[] byteArr)

    {

        Assembly.Load(byteArr);

    }


    // be careful here, only types from currently loaded assemblies can be passed as parameters / return value.

    // also, all parameters / return values from this object must be marked [Serializable]

    public string CreateAndExecutePluginResult(string assemblyQualifiedTypeName)

    {

        var domain = AppDomain.CurrentDomain;


        // we use this overload of GetType which allows us to pass in a custom AssemblyResolve function

        // this allows us to get a Type reference without searching the disk for an assembly.

        var pluginType = Type.GetType(

            assemblyQualifiedTypeName,

            (name) => domain.GetAssemblies().Where(a => a.FullName == name.FullName).FirstOrDefault(),

            null,

            true);


        dynamic plugin = Activator.CreateInstance(pluginType);


        // do whatever you want here with the instantiated plugin

        string result = plugin.RunTest();


        // remember, you can only return types which are already loaded in the primary app domain and can be serialized.

        return result;

    }

}

在這里,我將在上面的評論中重申一些要點(diǎn):


您必須繼承自MarshalByRefObject,這意味著可以使用遠(yuǎn)程處理跨應(yīng)用程序域邊界代理對此對象的調(diào)用。

將數(shù)據(jù)傳遞到代理類或從代理類傳遞數(shù)據(jù)時(shí),必須對數(shù)據(jù)進(jìn)行標(biāo)記,[Serializable]并且還必須采用當(dāng)前加載的程序集中的類型。如果您需要插件將某些特定對象返回給您,則說PluginResultModel您應(yīng)該在由兩個(gè)程序集/應(yīng)用程序域加載的共享程序集中定義此類。

必須將程序集合格的類型名傳遞給CreateAndExecutePluginResult其當(dāng)前狀態(tài),但是可以通過自己迭代程序集和類型并刪除對的調(diào)用來消除此要求Type.GetType。

接下來,您需要?jiǎng)?chuàng)建域并運(yùn)行代理:


static void Main(string[] args)

{

    var bytes = File.ReadAllBytes(@"...filepath...");

    var domain = AppDomain.CreateDomain("plugintest", null, null, null, false);

    var proxy = (PluginRunner)domain.CreateInstanceAndUnwrap(typeof(PluginRunner).Assembly.FullName, typeof(PluginRunner).FullName);

    proxy.LoadAssembly(bytes);

    proxy.CreateAndExecutePluginResult("TestPlugin.Class1, TestPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");

}

再說一遍,因?yàn)樗浅V匾?,而且我很長一段時(shí)間都不了解:當(dāng)您在此代理類上執(zhí)行方法時(shí),例如proxy.LoadAssembly實(shí)際上是被序列化為字符串并傳遞給新應(yīng)用程序要執(zhí)行的域。這不是正常的函數(shù)調(diào)用,您需要非常小心傳入/傳出這些方法的內(nèi)容。


查看完整回答
反對 回復(fù) 2021-05-23
?
哆啦的時(shí)光機(jī)

TA貢獻(xiàn)1779條經(jīng)驗(yàn) 獲得超6個(gè)贊

此調(diào)用導(dǎo)致System.IO.FileNotFoundException,但我不知道為什么。我懷疑會(huì)發(fā)生異常,因?yàn)樵俅卧诖疟P上搜索了程序集。但是,為什么程序要再次加載它?


這里的關(guān)鍵是了解加載程序上下文,有關(guān)MSDN的一篇很好的文章:


將加載程序上下文視為保存程序集的應(yīng)用程序域中的邏輯存儲區(qū)。根據(jù)程序集的加載方式,它們屬于三種加載程序上下文之一。


加載上下文

LoadFrom上下文

兩種情況都沒有

從裝byte[]配件將裝配件放置在這兩個(gè)上下文中。


至于這兩個(gè)上下文,除非應(yīng)用程序預(yù)訂AssemblyResolve事件,否則不能綁定該上下文中的程序集。通常應(yīng)避免這種情況。


在下面的代碼中,我們使用AssemblyResolve事件在Load上下文中加載程序集,從而使我們能夠綁定到該程序集。


如何使用從字節(jié)數(shù)組加載的程序集在新的appdomain中創(chuàng)建實(shí)例?


請注意,這僅僅是概念的證明,它是探索裝載程序上下文的基本要素。建議的方法是使用@caesay描述的代理,并在本文中由Suzanne Cook進(jìn)一步評論。


這是一個(gè)不保留對實(shí)例的引用的實(shí)現(xiàn)(類似于即發(fā)即棄)。


首先,我們的插件:


Test.cs


namespace Plugins

{

    public class Test

    {

        public Test()

        {

            Console.WriteLine($"Hello from {AppDomain.CurrentDomain.FriendlyName}.");

        }

    }

}

接下來,在一個(gè)新ConsoleApp的插件加載器中:


PluginLoader.cs


[Serializable]

class PluginLoader

{

    private readonly byte[] _myBytes;

    private readonly AppDomain _newDomain;


    public PluginLoader(byte[] rawAssembly)

    {

        _myBytes = rawAssembly;

        _newDomain = AppDomain.CreateDomain("New Domain");

        _newDomain.AssemblyResolve += new ResolveEventHandler(MyResolver);

    }


    public void Test()

    {

        _newDomain.CreateInstance("plugin", "Plugins.Test");

    }


    private Assembly MyResolver(object sender, ResolveEventArgs args)

    {

        AppDomain domain = (AppDomain)sender;

        Assembly asm = domain.Load(_myBytes);

        return asm;

    }

}

Program.cs


class Program

{

    static void Main(string[] args)

    {

        byte[] rawAssembly = File.ReadAllBytes(@"D:\Projects\AppDomainTest\plugin.dll");

        PluginLoader plugin = new PluginLoader(rawAssembly);


        // Output: 

        // Hello from New Domain

        plugin.Test();


        // Output: 

        // Assembly: mscorlib

        // Assembly: ConsoleApp

        foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())

        {

            Console.WriteLine($"Assembly: {asm.GetName().Name}");

        }


        Console.ReadKey();

    }

}

CreateInstance("plugin", "Plugins.Test")盡管不了解插件程序集,但顯示的輸出已成功從默認(rèn)應(yīng)用程序域中成功調(diào)用。


查看完整回答
反對 回復(fù) 2021-05-23
  • 3 回答
  • 0 關(guān)注
  • 231 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號