Любой способ «безопасно» вызвать сборку. GetTypes ()? - PullRequest
20 голосов
/ 12 апреля 2011

Я искал все выше и ниже, но не могу найти решение для этого.

Мне нужно получить все типы интерфейсов из сборки со следующим кодом:

IEnumerable<Type> interfaces = _assembly.GetTypes().Where(x => x.IsInterface);

Проблема в том, что для некоторых сборок я сталкиваюсь со следующей ошибкой:

Невозможно загрузить один или несколько запрашиваемые типы. Получить Свойство LoaderExceptions для более информация.

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

Я хотел бы знать, есть ли способ разрешить коду продолжать работу после любых типов, которые не могут быть извлечены, и по-прежнему извлекать те, которые не дают ошибок.

Ответы [ 2 ]

32 голосов
/ 12 апреля 2011

Похоже, что это неприятный API, для которого нельзя избежать исключения (насколько я знаю).

Попробуйте что-то вроде этого:

IEnumerable<Type> interfaces;
try
{
    interfaces = _assembly.GetTypes().Where(x => x.IsInterface);
}
catch (ReflectionTypeLoadException ex)
{
    interfaces = ex.Types.Where(x => x != null && x.IsInterface);
}

UPDATE

На самом деле, это так безобразно , что я, вероятно, где-то спрятал бы это. Это, должно быть, очень старая часть .NET Framework, потому что я уверен, что в наши дни они не будут так ее проектировать.

private static IEnumerable<Type> GetTypesSafely(Assembly assembly)
{
    try
    {
        return assembly.GetTypes();
    }
    catch(ReflectionTypeLoadException ex)
    {
        return ex.Types.Where(x => x != null);
    }
}

...
IEnumberable<Type> interfaces = GetTypesSafely(_assembly).Where(x => x.IsInterface);

Если вы думаете, что будете делать это очень часто, то метод расширения может быть более подходящим.

0 голосов
/ 12 апреля 2011

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

IEnumerable<Type> interfaces = _assembly.GetTypes().Where(IsInterface);

List<string> Messages = new List<string>();

private bool IsInterface(Type x)
{
    try { return x.IsInterface; }
    catch (Exception e)
    {
        Messages.Add(e.Message);
    }
    return false;
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...