我正在尝试通过遵循此 article 来实现 CQRS ,我的一切正常,但我不知道如何在 Unity 中注册所有 IQueryHandler 类型。
我有以下类(class):
// query
public class GetTitleByIdQuery : IQuery
{
public int Id { get; set; }
}
//result
public class GetTitleByIdResult : IQueryResult
{
public int Id { get; set; }
public string Description { get; set; }
}
// handler
public class GetTitleById : IQueryHandler<GetTitleByIdQuery, GetTitleByIdResult>
{
public async Task<GetTitleByIdResult> Retrieve(GetTitleByIdQuery query)
{
var context = new MyContext();
return await context.Titles.Where(i => i.Id == query.id).Select(i => new GetTitleByIdResult {Id = i.Id, Description = i.Description}).SingleAsync();
}
}
如果我明确注册类型,它会得到正确解析,例如
container.RegisterType<IQueryHandler<GetTitleByIdQuery, GetTitleByIdResult>, GetTitleById>();
解决方式:
GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IQueryHandler<TParameter, TResult>));
但是这意味着我必须手动注册每种类型,理想情况下我想做类似的事情:
container.RegisterTypes(
AllClasses.FromLoadedAssemblies().Where(type => typeof(IQueryHandler<,>).IsAssignableFrom(type)),
WithMappings.FromAllInterfaces, WithName.TypeName, WithLifetime.Transient);
当我尝试这样做时,没有任何类型被注册,我认为这是因为它们不可分配,例如,这是无效的语法:
IQueryHandler<IQuery, IQueryResult> test = new GetTitleById();
原文章的作者似乎可以使用Ninject来做到这一点,在Unity中也可以吗?
最佳答案
您可以添加扩展方法 RegisterAllTypesForOpenGeneric
,例如:
container.RegisterAllTypesForOpenGeneric(typeof(IQueryHandler<,>), Assembly.GetAssembly(typeof(GetTitleById )));
与:
public static class UnityExtensions
{
public static void RegisterAllTypesForOpenGeneric(this IUnityContainer container, Type openGenericType, Assembly targetAssembly)
{
if (!openGenericType.IsGenericTypeDefinition)
throw new ArgumentException("typeToRegister must be an open generic type", "typeToRegister");
foreach (Type type in targetAssembly.GetExportedTypes())
{
if (openGenericType.IsInterface)
RegisterInterfaceTypes(container, openGenericType, type, type);
else
RegisterBaseTypes(container, openGenericType, type, type);
}
}
private static void RegisterInterfaceTypes(IUnityContainer container, Type openGenericType, Type targetType, Type typeToRegister)
{
foreach (Type interfaceType in targetType.GetInterfaces())
if (interfaceType.IsGenericType && !interfaceType.ContainsGenericParameters && openGenericType.IsAssignableFrom(interfaceType.GetGenericTypeDefinition()))
container.RegisterType(interfaceType, typeToRegister);
}
private static void RegisterBaseTypes(IUnityContainer container, Type openGenericType, Type targetType, Type typeToRegister)
{
if (targetType.BaseType != null && targetType.BaseType != typeof(object))
if (targetType.BaseType.IsGenericType && openGenericType.IsAssignableFrom(targetType.BaseType.GetGenericTypeDefinition()))
container.RegisterType(targetType.BaseType, typeToRegister);
else
RegisterBaseTypes(container, openGenericType, targetType.BaseType, typeToRegister);
}
}
来源:http://www.danderson00.com/2010/09/automatically-register-implementors-of.html
关于c# - Unity - 使用接口(interface)参数注册通用类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30192962/