Get All Types Implementing Specific Open Generic Type

Get all types implementing specific open generic type

This will return all types that inherit a generic base class. Not all types that inherit a generic interface.

var AllTypesOfIRepository = from x in Assembly.GetAssembly(typeof(AnyTypeInTargetAssembly)).GetTypes()
let y = x.BaseType
where !x.IsAbstract && !x.IsInterface &&
y != null && y.IsGenericType &&
y.GetGenericTypeDefinition() == typeof(IRepository<>)
select x;

This will return all types, including interfaces, abstracts, and concrete types that have the open generic type in its inheritance chain.

public static IEnumerable<Type> GetAllTypesImplementingOpenGenericType(Type openGenericType, Assembly assembly)
{
return from x in assembly.GetTypes()
from z in x.GetInterfaces()
let y = x.BaseType
where
(y != null && y.IsGenericType &&
openGenericType.IsAssignableFrom(y.GetGenericTypeDefinition())) ||
(z.IsGenericType &&
openGenericType.IsAssignableFrom(z.GetGenericTypeDefinition()))
select x;
}

This second method will find ConcreteUserRepo and IUserRepository in this example:

public class ConcreteUserRepo : IUserRepository
{}

public interface IUserRepository : IRepository<User>
{}

public interface IRepository<User>
{}

public class User
{}

Get all implementations types of a generic interface

You can try working example.

Declarations:

public interface IEntity { }
public class Entity1 : IEntity { }
public class Entity2 : IEntity { }

public interface IEntityModelBuilder<out T> where T : IEntity { }

public class BaseClass1 : IEntityModelBuilder<Entity1>
{
public BaseClass1(int a) { }
}
public class BaseClass2 : IEntityModelBuilder<Entity2>
{
public BaseClass2(int a) { }
}

Usage:

List<IEntityModelBuilder<IEntity>> objects = Assembly.GetExecutingAssembly().GetTypes()
.Where(x => x.GetInterfaces().Any(y => y.IsGenericType && && y.Name == "IEntityModelBuilder`1"))
.Select(x => (IEntityModelBuilder<IEntity>)Activator.CreateInstance(x, new object[] { 0 })).ToList();

Find all types implementing a certain generic interface with specific T type

This condition is incorrect:

x.IsAssignableFrom(typeof(ICanHandleIntent<>))

a type implementing an instance of a generic interface is not assignable from the generic interface definition itself, which ICanHandleIntent<> represents.

What you want instead is

x.GetGenericTypeDefinition() == typeof(ICanHandleIntent<>)

The check for the type parameter is also wrong. It should be

x.GetGenericArguments()[0] == intent.GetType()

because you are looking for the type argument, i.e. the type in triangular brackets following the generic name.

Get all implementations of a generic service type - including open generics

A call to RegisterOpenGeneric will in the background hook a delegate onto the ResolveUnregisteredType event. This basically means that the container itself is completely unaware of the registration, and the registration will only get added when a closed-generic version of the registered abstraction is requested; either directly using a call to GetInstance() or indirectly because a type that depends on that abstraction is resolved.

The trick here is to call Verify() before calling GetCurrentRegistrations(). A call to Verify() will cause the container to build all expression trees, compile all delegates, and create all instances of all registrations that are known to the container. This will force the container to add the registrations of each found closed-generic version of that open-generic abstraction.

Long story short: call Verify() first.

.NET - Getting all implementations of a generic interface?

You can use something like this:

public static bool DoesTypeSupportInterface(Type type, Type inter)
{
if(inter.IsAssignableFrom(type))
return true;
if(type.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == inter))
return true;
return false;
}

public static IEnumerable<Type> TypesImplementingInterface(Type desiredType)
{
return AppDomain
.CurrentDomain
.GetAssemblies()
.SelectMany(assembly => assembly.GetTypes())
.Where(type => DoesTypeSupportInterface(type, desiredType));

}

It can throw a TypeLoadException though but that's a problem already present in the original code. For example in LINQPad it doesn't work because some libraries can't be loaded.

Getting all types that implement an interface

Mine would be this in c# 3.0 :)

var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));

Basically, the least amount of iterations will always be:

loop assemblies  
loop types
see if implemented.

Generic type from base interface

Search type interfaces for generic interface which is Foo<>. Then get first generic argument of that interface:

type.GetInterfaces()
.FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(Foo<>))
?.GetGenericArguments().First();

If you want to check whether type is implementing Foo<>:

type.GetInterfaces()
.Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(Foo<>))

Get type that implements generic interface by searching for a specific generic interface parameter

To refactor @lucky's answer, I prefer comparing the types with the generic type definition instead of using the type name:

static readonly Type GenericIEnumerableType = typeof(IEnumerable<>);

//Find all types that implement IEnumerable<T>
static IEnumerable<T> FindAllEnumerableTypes<T>(Assembly assembly) =>
assembly
.GetTypes()
.Where(type =>
type
.GetInterfaces()
.Any(interf =>
interf.IsGenericType
&& interf.GetGenericTypeDefinition() == GenericIEnumerableType
&& interf.GenericTypeArguments.Single() == typeof(T)));

Alternatively, you can check if interf is assignable from GenericIEnumerableType.MakeGenericType(typeof(T)) or the other way around.

autofac Resolve all types of open generic type?

As explained in the comments, what you want is impossible to achieve in C# and with good reason. If you were able to cast an IHandleEvent<EventOne> to an IHandleEvent<IEvent> it would allow an EventTwo to be passed in as well, which would fail at runtime.

So what you need is an mediator abstraction that allow getting all the compatible event handlers and call them. Such mediator is often called IEventPublisher and might look like this:

public interface IEventPublisher {
void Publish(IEvent e);
}

You can now create a container specific implementation. For instance, for Autofac this would look as follows:

public class AutofacEventPublisher : IEventPublisher {
private readonly IComponentContext container;

public AutofacBusinessRuleValidator(IComponentContext container) {
this.container = container;
}

public void Publish(IEvent e) {
foreach (dynamic handler in this.GetHandlers(e.GetType())) {
handler.Handle((dynamic)e);
}
}

private IEnumerable GetHandlers(Type eventType) =>
(IEnumerable)this.container.Resolve(
typeof(IEnumerable<>).MakeGenericType(
typeof(IHandleEvent<>).MakeGenericType(eventType)));
}

Consumers can now depend on this new abstraction:

class AService : IAService
{
public AService(IEventPublisher publisher) {...}
}

Find implementation of generic interface

You might be interested in reading Simple Injector's fine manual on doing Auto-Registration, as the the block of posted code can be reduced to a simple one-liner:

container.Register(typeof(ICommandHandler<>), AppDomain.CurrentDomain.GetAssemblies());


Related Topics



Leave a reply



Submit