Как я могу получить тип из ссылочной сборки через отражение - PullRequest
6 голосов
/ 18 февраля 2010

Предположим, у меня есть фабричный метод, который хочет создать экземпляр типа, выбранного во время выполнения с помощью отражения. Предположим далее, что мой метод фабрики является общим кодом, который не ссылается непосредственно на сборку, содержащую указанный тип, хотя он будет запускаться из приложения, на которое ссылается необходимая сборка.

Как мне написать код, который может найти этот тип? Если я сделаю следующее

public object CreateInstance(string typeName)
{
    Type desiredType = Assembly.GetExecutingAssembly().GetType(typename);

    // Instantiate the type...
}

это похоже на ошибку, потому что тип не определен в исполняемой сборке. Если бы я мог получить все сборки, доступные во время выполнения, я мог бы перебрать их и найти, какая из них содержит нужный мне тип. Но я не вижу способа сделать это. AppDomain.CurrentDomain.GetAssemblies() выглядит многообещающе, но не возвращает все сборки, на которые я ссылался в моем проекте.

Редактировать : Несколько человек указали, что мне нужно загрузить сборку. Проблема в том, что этот фрагмент кода не знает, какую сборку он должен загрузить, поскольку я пытаюсь написать этот код таким образом, чтобы он не зависел от других сборок.

Я сознательно пропустил детали typeName, поскольку отображение из строки в тип в моем реальном коде на самом деле более сложное. На самом деле, тип определяется пользовательским атрибутом, который содержит указанную строку, но если я смогу получить список типов, у меня нет проблем с ограничением списка требуемым типом.

Ответы [ 3 ]

12 голосов
/ 18 февраля 2010

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

var t = Assembly
   .GetExecutingAssembly()
   .GetReferencedAssemblies()
   .Select(x => Assembly.Load(x))
   .SelectMany(x => x.GetTypes()).First(x => x.FullName == typeName);

Хотя это может быть не самым эффективным. Опять же, вы используете отражение.

11 голосов
/ 18 февраля 2010

Вызов AppDomain.CurrentDomain.GetAssemblies() возвращает только набор DLL, которые в настоящее время загружены в AppDomain. DLL загружаются в процесс CLR по требованию; следовательно, он не будет включать в себя все библиотеки DLL, на которые есть ссылки в вашем проекте, пока одна из них не будет фактически использована.

Что вы можете сделать, так это запустить сборку в процессе с помощью выражения typeof. Например

var force1 = typeof(SomeTypeInTheProject).Assembly;
var force2 = typeof(SomeTypeInProject2).Assembly;
3 голосов
/ 18 февраля 2010

AppDomain.CurrentDomain.GetAssemblies() возвращает только загруженные сборки. Поэтому вам нужно загрузить эту сборку, на которую есть ссылки, если она еще не загружена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...