I've searched high and low, but I can't come up with a solution for this.
I need to get all the interface types from an assembly with code like this:
IEnumerable<Type> interfaces = _assembly.GetTypes().Where(x => x.IsInterface);
The problem is, for certain assemblies I run into the following error:
Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
I'm completely clear on why this happens (dependant assemblies are not loaded), and how it can be worked around if I want to troubleshoot a specific assembly. In my case, I don't know the assembly 开发者_开发百科up front (the user will select it).
What I'd like to know is whether there is any way to allow the code to continue past any types that can't be retrieved, and still pull the ones that don't fail.
It looks like this is a vexing API for which the exception cannot be avoided (as far as I know).
Try something like this:
IEnumerable<Type> interfaces;
try
{
interfaces = _assembly.GetTypes().Where(x => x.IsInterface);
}
catch (ReflectionTypeLoadException ex)
{
interfaces = ex.Types.Where(x => x != null && x.IsInterface);
}
UPDATE
Actually, this is so ugly that I would probably hide it somewhere. This must be a very old part of the .NET Framework, because I’m pretty sure they wouldn't design it like this nowadays.
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);
If you think you'll be doing this very often, then an extension method might be more appropriate.
Handle the exception in another method that takes the place of the lambda expression and catches the exception. You could also have the exceptions accumulate in some global object for inspection later.
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;
}
精彩评论