I’m looking for all implementations of IHandle<> in my assembly.
public interface IHandle<T> where T : class, IEvent, new()
Those classes looks like
public class IHandleEventX : IHandle<EventX>{...}
public class IHandleAnotherEvent : IHandle<AnotherEvent>{...}
Currently, I got the following code.
aLoader.LoadImplementationOf(typeof(IHandle<>));
// my aLoader class method
public void LoadImplementationOf(Type genericInterface)
{
// theres another foreach here, to iterate over all assemblies
foreach (Type aType in allMyAssemblies.GetTypes())
{
var interfaces = aType.GetInterfaces();
foreach (var currentInterface in interfaces)
{
if (!currentInterface.IsGenericType) { continue; }
// the statement below always return false
if (currentInterface.GetGenericTypeDefinition() == genericInterface)
{}
// those two statement (FullName and AssemblyQualifiedName), works as expected
if (currentInterface.GetGenericTypeDefinition().FullName == genericInterface.FullName)
{}
if (currentInterface.GetGenericTypeDefinition().AssemblyQualifiedName == genericInterface.AssemblyQualifiedName)
{}
// those below also fail
if (currentInterface.GetGenericTypeDefinition().IsAssignableFrom(genericInterface))
{}
if (genericInterface.IsAssignableFrom(currentInterface.GetGenericTypeDefinition()))
{}
// can't do currentInterface.GetGenericTypeDefinition() is genericInterface compiler error
}
}
Why comparing types fail, but comparing types fullname property works ?
Also, whats the best way to do this?
Edit: I rewrote the sample, using only one assembly and IsAssignableFrom worked. I’ll investigate and update here later to see why isn’t working using more than one assembly – as @HansPassant pointed out
It’s working now, but I’m not sure why…
I was working with 3 assemblies.
- Asm Loader, there was only de ALoader class there
- Asm Domain, with interfaces IHandle<>, IEvent<> and classes IHandleEventX, IHandleAnotherEvent
- Asm Test, my test project, I was calling aLoader.LoadImplementationOf(typeof(IHandle<>)); from here.
Projects References.
- Loader doesnt references any project.
- Domain references Loader (there was another IInterface on Loader, implemented on Domain)
- Test references both Loader and Domain.
So I moved my interfaces IHandle<> and IEvent<> from Domain to Loader and removed the reference from Domain to Loader, now, its works.
Its still not clear why the IsAssignableFrom failed when IHandle<> was in the domain. It only worked when my IHandle<> and ALoader are in the same assembly.
Well, in the end, that was my fault, I was loading de assembly in two load contexts.
That’s because Type.FullName doesn’t fully describe a type. You only get the namespace name and the type name. But .NET also includes the properties of the assembly in which the type resides into the type identity. Display name, [AssemblyVersion], Culture, PublicKeyToken and (indirectly) ProcessorArchitecture. You want to compare
Type.AssemblyQualifiedNameinstead.The diagnostic for failure like this is that the source code that contains the interface definition is getting compiled into multiple assemblies. Which in itself is almost always a mistake, you want to make sure that such an interface type only exists in one assembly. And any assembly that uses the interface type has a reference to it so they all use an identical type.
The rules for type identity were loosened somewhat in .NET 4, a type can be identical if it has the same GUID. The underlying core for the Embed Interop Types feature. But that only applies to [ComImport] types, I doubt that’s the case here.