AppDomain.CreateInstance не следует правилам - PullRequest
2 голосов
/ 03 февраля 2010

Согласно Как во время выполнения обнаруживаются сборки Шаг 2 равен Проверка ранее связанных сборок .

Однако в приведенном ниже коде вы можете видеть, что этого точно не происходит. В первой строке загружается сборка (что делает ее «сборкой, на которую ссылаются ранее» для всех будущих вызовов).

Однако через пару строк, когда код вызывает AppDomain.CurrentDomain.CreateInstance, происходит событие AssemblyResolve, указывающее, что среда выполнения не может найти запрошенную сборку.

Вы можете сказать, что сборка загружена, потому что из события AssemblyResolve Я возвращаю сборку напрямую из CurrentDomain.GetAssemblies () !!

Итак, очевидный вопрос заключается в том, почему среда выполнения не находит ссылочную сборку, как подразумевается в шаге 2 раздела «Как среда выполнения находит сборки»?

Чтобы запустить этот пример: создайте новое консольное приложение, затем добавьте новую ClassLibrary к этому решению и оставьте ее с именем ClassLibrary1. Вставьте приведенный ниже код в программу класса Консольного приложения:

class Program
{
    static void Main(string[] args)
    {
        Assembly asmbly = Assembly.LoadFile(Path.GetFullPath(@"..\..\..\ClassLibrary1\bin\Debug\ClassLibrary1.dll"));
        Type firstType = asmbly.GetTypes().First();
        AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
        object myInstance = AppDomain.CurrentDomain.CreateInstance(asmbly.FullName, firstType.FullName);
    }

    static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        //WHY AM I HERE?
        return AppDomain.CurrentDomain.GetAssemblies().SingleOrDefault(p => p.FullName == args.Name);
    }
}

затем добавьте ссылки, например, так:

using System.Reflection;
using System.IO;

Обратите внимание, что я намеренно оставил здесь исходные пути, так что среда выполнения не найдет сборку в соответствии с Шаг 4. Поиск сборки по кодовым базам или зондированию Мой сценарий таков, что Я пытаюсь сознательно использовать функциональность, определенную в Шаг 2 . Если среда выполнения может определить путь с помощью шага 4, это будет работать правильно. Это шаг 2, который не работает.

Спасибо.

Ответы [ 2 ]

3 голосов
/ 03 февраля 2010

Не удается разрешить, потому что сборка была загружена в другой контекст - контекст LoadFile, в то время как AppDomain.CurrentDomain.CreateInstance пытается разрешить сборку, используя контекст загрузки.

Из "Понимание контекста" в Понимание механизма связывания CLR :

Так почему же CLR в первую очередь имеет контексты загрузчика?Контексты загрузчика помогают обеспечить независимость порядка загрузки при загрузке сборок.Кроме того, они обеспечивают меру изоляции для сборок и их зависимостей, когда они загружаются в различные контексты.

Похоже, что вы уже решили проблему, подписавшись на событие AssemblyResolve,но есть несколько других подходов, которые вы можете использовать, в зависимости от ваших требований:

2 голосов
/ 03 февраля 2010

Это цитата из MSDN

Используйте метод LoadFile для загрузки и проверки сборок, которые имеют одинаковые идентификационные данные, но расположены по разным путям.LoadFile не загружает файлы в контекст LoadFrom и не разрешает зависимости, используя путь загрузки, как это делает метод LoadFrom.LoadFile полезен в этом ограниченном сценарии, потому что LoadFrom не может использоваться для загрузки сборок, которые имеют одинаковые идентификаторы, но разные пути;он загрузит только первую такую ​​сборку.

Вот отличная статья , в которой подробно рассказывается о том, как метод, используемый для загрузки сборки, влияет на разрешение ссылок.

InВ частности, в этой статье говорится, что LoadFile загружает сборку в «ни один контекст».

...