I have the following interfaces:
public interface IQuery<TResult>
{
}
public interface IQueryHandler<in TQuery, out TResult> where TQuery : IQuery<TResult>
{
TResult Handle(TQuery query);
}
One of my implementing queries is:
public class ApplyPermissionSetForUserAndPermissionTypeQuery<TQueryable, TEntity> : IQuery<TQueryable>
where TQueryable : IQueryable<TEntity>
{
}
and it's handler:
public class ApplyPermissionSetForUserAndPermissionTypeHandler<TQueryable, TEntity> : IQueryHandler<ApplyPermissionSetForUserAndPermissionTypeQuery<TQueryable, TEntity>, TQueryable>
where TQueryable : IQueryable<TEntity>
{
}
When building my container I call:
container.Register(typeof(IQueryHandler<,>), container.Settings.QueryHandlerAssemblies);
Which register all the types in the assembiles passed and has worked for all of my other handles. The problem one is different in so much that the query and handler contain a generic type themselves.
I currently have the ResolveUnregisteredType event registered on the container doing the following:
private void container_ResolveUnregisteredType(object sender, SimpleInjector.UnregisteredTypeEventArgs e)
{
var serviceType = e.UnregisteredServiceType;
if (serviceType.IsGenericType &&
serviceType.GetGenericTypeDefinition() == typeof(IQueryHandler<,>))
{
var queryArg = serviceType.GetGenericArguments()[0];
var resultArg = serviceType.GetGenericArguments()[1];
if (queryArg.IsGenericType &&
queryArg.GetGenericTypeDefinition() == typeof(ApplyPermissionSetForUserAndPermissionTypeQuery<,>))
{
var itemTypeArgument = queryArg.GetGenericArguments()[0];
var entityTypeArgument = queryArg.GetGenericArguments()[1];
if (itemTypeArgument != resultArg)
return;
Type typeToRegister;
try
{
typeToRegister = typeof(ApplyPermissionSetForUserAndPermissionTypeHandler<,>).MakeGenericType(itemTypeArgument, entityTypeArgument);
}
catch (ArgumentException)
{
// Thrown by MakeGenericType when the type constraints
// do not match. In this case, we don't have to register
// anything and can bail out.
return;
}
//Register a delegate which will return
e.Register(delegate () { return GetInstance(typeToRegister); });
}
}
}
Which is making it work so I know it is possible to register the type. This leads me to believe I'm missing something obvious, e.g. the type is just not being registered by the "container.Register(typeof(IQueryHandler<,>), container.Settings.QueryHandlerAssemblies)" method.
Is it possible to make simple injector register this type automatically and do it in such a way that I can just register assemblies as I will not know explicit types all the time. E.g. the list of assemblies can be variable and contain unknown queries within them so I can't just make calls to:
container.Register(typeof(IQueryHandler<,>), typeof(IQueryHandler<ApplyPermissionSetForUserAndPermissionTypeQuery<,>,>))
Or will I have to enumerate the assemblies myself looking for IQueryHandler<,> types which take generic types and register them, or just change my event handler to be generic in of it's self?