Unity 3.5:通过其开放的通用接口检索具体实现
本文关键字:检索 接口 实现 Unity | 更新日期: 2023-09-27 18:13:13
这篇博文描述了Repository模式的一个很好的替代方案。
https://cuttingedge.it/blogs/steven/pivot/entry.php?id = 92
作者建议使用命令和查询代替存储库。这篇博文描述了在。net/c#中查询部分的实现。
查询和查询处理程序有两个接口:public interface IQuery<TResult>
{
}
public interface IQueryHandler<TQuery, TResult> where TQuery : IQuery<TResult>
{
TResult Handle(TQuery query);
}
他还提供了每个例子:
public class FindUsersBySearchTextQuery : IQuery<User[]>
{
public string SearchText { get; set; }
public bool IncludeInactiveUsers { get; set; }
}
public class FindUsersBySearchTextQueryHandler
: IQueryHandler<FindUsersBySearchTextQuery, User[]>
{
private readonly NorthwindUnitOfWork db;
public FindUsersBySearchTextQueryHandler(NorthwindUnitOfWork db)
{
this.db = db;
}
public User[] Handle(FindUsersBySearchTextQuery query)
{
return (
from user in this.db.Users
where user.Name.Contains(query.SearchText)
select user)
.ToArray();
}
}
查询处理程序可以作为MVC控制器的构造函数参数提供。
public class UserController : Controller
{
IQueryHandler<FindUsersBySearchTextQuery, User[]> handler;
public UserController(IQueryHandler<FindUsersBySearchTextQuery, User[]> handler)
{
this.handler = handler;
}
public View SearchUsers(string searchString)
{
var query = new FindUsersBySearchTextQuery
{
SearchText = searchString,
IncludeInactiveUsers = false
};
User[] users = this.handler.Handle(query);
return this.View(users);
}
}
作者使用依赖注入容器Simple Injector一次性注册所有的IQueryHandler:
container.RegisterManyForOpenGeneric(
typeof(IQueryHandler<,>),
typeof(IQueryHandler<,>).Assembly);
我的问题是:我如何在Unity中执行最后一个语句?
我使用Unity 3.5。
我可以手动注册每个QueryHandler,像这样:
container.RegisterType<IQueryHandler<FindUsersBySearchTextQuery, User[]>,
FindUsersBySearchTextQueryHandler>();
这工作得很好,但我不想在每次新的QueryHandler出现时添加新的映射。我想用一个约定来设置所有映射,其中包括未来的QueryHandler。Unity 3.5提供了一个基于约定的注册工作流程,但我不能让它为我的情况工作。我试过了,但不幸的是它没有生成问题中的映射。
container.RegisterTypes(
AllClasses.FromLoadedAssemblies(),
WithMappings.FromMatchingInterface,
WithName.Default);
如果您将有许多特定的IQueryHandler<,>
实现,而不是一个通用版本,那么您不能使用开放泛型来注册。但是您可以使用反射来查找所有实现并分别注册它们。(这就是RegisterTypes在幕后为你做的事情)。
您在问题中尝试使用RegisterTypes调用,但是您使用了WithMappings.FromMatchingInterface
。这将只注册与MyClass : IMyClass
命名约定匹配的接口的类(在类名前加上'I'
)。如果你用WithMappings.FromAllInterfaces
注册,你将得到你想要的注册。
container.RegisterTypes(
AllClasses.FromLoadedAssemblies(),
WithMappings.FromAllInterfaces,
WithName.Default);
如果你只需要注册那些类,你可以过滤掉那些类,只实现你想要的接口…
public static class EnumerableTypeExtensions
{
public static IEnumerable<Type> WhichImplementsInterface<T>
(this IEnumerable<Type> types)
{
return types.WhichImplementsInterface(typeof (T));
}
public static IEnumerable<Type> WhichImplementsInterface
(this IEnumerable<Type> types, Type interfaceType)
{
return types.WhichImplementsInterface(interfaceType.Name);
}
public static IEnumerable<Type> WhichImplementsInterface
(this IEnumerable<Type> types, string interfaceTypeName)
{
return types.Where(t => t.GetInterface(interfaceTypeName) != null);
}
}
然后你可以像这样使用这些过滤器…
container.RegisterTypes(
AllClasses.FromLoadedAssemblies().WhichImplementsInterface(typeof(IQueryHandler<,>)),
WithMappings.FromAllInterfaces,
WithName.Default);