Загрузка DLL в отдельный домен приложений - PullRequest
4 голосов
/ 22 декабря 2010

Я пишу плагин архитектуры.Мои dll плагина находятся в подкаталоге, из которого запущен менеджер плагинов.Я загружаю плагины в отдельный домен приложений следующим образом:

string subDir;//initialized to the path of the module's directory.
AppDomainSetup setup = new AppDomainSetup();
setup.PrivateBinPath = subDir;
setup.ApplicationBase = subDir;

AppDomain newDomain= AppDomain.CreateDomain(subDir, null, setup);

byte[] file = File.ReadAllBytes(dllPath);//dll path is a dll inside subDir
newDomain.Load(file);

Однако.newDomain.Load возвращает сборку, которую пытается загрузить текущий домен.Поскольку dll плагина находятся в подкаталоге, текущий домен не может и не должен видеть эти dll, а текущий домен создает исключение FileLoadException "ex = {" Не удалось загрузить файл или сборку ... или одну из ее зависимостей. "*

Вопрос в том, можем ли мы загрузить сборку в отдельный домен приложений без возврата загруженной сборки?

Я знаю, что могу добавить обработчик для события AssemblyResolve в текущем домене и вернуть нольно я бы предпочел не идти по этому пути.

Заранее спасибо.

Ответы [ 2 ]

5 голосов
/ 27 января 2012

Вы также можете использовать DoCallBack - вот кое-что, что я собрал, прочитав много об этом в SO.Это создает домен приложения, проверяет, что сборки имеют одинаковый открытый ключ подписи, загружает сборку, выполняет статический метод, выгружает домен приложения, а затем удаляет DLL.

static void Main(string[] args)
    {
        string unknownAppPath = @"path-to-your-dll";

        Console.WriteLine("Testing");
        try
        {
            AppDomainSetup setup = new AppDomainSetup();
            setup.AppDomainInitializer = new AppDomainInitializer(TestAppDomain);
            setup.AppDomainInitializerArguments = new string[] { unknownAppPath };
            AppDomain testDomain = AppDomain.CreateDomain("test", AppDomain.CurrentDomain.Evidence, setup);
            AppDomain.Unload(testDomain);
            File.Delete(unknownAppPath);
        }
        catch (Exception x)
        {
            Console.WriteLine(x.Message);
        }
        Console.ReadKey(); 
    }

    public static void TestAppDomain(string[] args)
    {
        string unknownAppPath = args[0];
        AppDomain.CurrentDomain.DoCallBack(delegate()
        {
            //check that the new assembly is signed with the same public key
            Assembly unknownAsm = AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName(unknownAppPath));
            //get the new assembly public key
            byte[] unknownKeyBytes = unknownAsm.GetName().GetPublicKey();
            string unknownKeyStr = BitConverter.ToString(unknownKeyBytes);
            //get the current public key
            Assembly asm = Assembly.GetExecutingAssembly();
            AssemblyName aname = asm.GetName();
            byte[] pubKey = aname.GetPublicKey();
            string hexKeyStr = BitConverter.ToString(pubKey);
            if (hexKeyStr == unknownKeyStr)
            {
                //keys match so execute a method
                Type classType = unknownAsm.GetType("namespace.classname");
                classType.InvokeMember("method-you-want-to-invoke", BindingFlags.InvokeMethod, null, null, null);
            }
        });
    }
2 голосов
/ 22 декабря 2010

Как указано в ссылках, приведенных ниже:

Загрузка / выгрузка сборки в другом домене приложений

Загрузка сборки в новый домен приложений без загрузки в родительский домен приложений

Похоже, что вызов метода Load() для другого объекта AppDomain также приводит к загрузке сборки в текущем AppDomain.

Решение заключается в использовании CreateInstanceFromAndUnwrap() метод AppDomain класса вместо.Вы передаете путь к сборке и тип для преобразования.

...