Подтвердить что ты не робот

Любой способ "безопасно" вызывать сборку .GetTypes()?

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

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

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

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

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

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

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

4b9b3361

Ответ 1

Похоже, что это досадный 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, потому что Im очень уверен, что они не будут создавать его так, как сейчас.

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);

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

Ответ 2

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

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;
}