任何“安全”调用assembly.GetTypes()的方法?

时间:2011-04-12 17:40:39

标签: c# reflection

我搜索过高低,但我无法想出解决方案。

我需要从程序集中获取所有类型的接口类型:

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

问题是,对于某些程序集,我遇到以下错误:

  

无法加载一个或多个   要求的类型。检索   LoaderExceptions属性更多   信息。

我完全清楚为什么会发生这种情况(未加载依赖程序集),以及如果我想对特定程序集进行故障排除,它是如何解决的。就我而言,我不知道前面的装配(用户会选择它)。

我想知道的是,是否有任何方法可以让代码继续通过任何无法检索的类型,并且仍然可以提取那些不会失败的类型。

2 个答案:

答案 0 :(得分:32)

看起来这是一个令人烦恼的API,无法避免异常(据我所知)。

尝试这样的事情:

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

<强>更新

实际上,这就是丑陋,我可能会把它隐藏在某个地方。这必须是.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);

如果您认为自己会经常这样做,那么扩展方法可能更合适。

答案 1 :(得分:0)

在另一个取代lambda表达式并捕获异常的方法中处理异常。您也可以在某些全局对象中累积异常以供稍后检查。

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