我有使用Repository Pattern的情况,我希望有一些额外的存储库与任何实体都不对应。
例如,这里有一个:
public class TargetRepository : RepositoryBase<Target>, ITargetRepository
{
public TargetRepository(IDatabaseFactory databaseFactory)
:base(databaseFactory)
{
}
public IEnumerable<Target> GetValidTargets(){ ... }
}
public interface ITargetRepository : IRepository<Target>
{
IEnumerable<Target> GetValidTargets();
}
Target
是一个实体。
然后我想要一些像这样的其他存储库:
public class ScatterPlotRepositoryProxy : TargetRepository, IScatterPlotRepositoryProxy
{
public ScatterPlotRepositoryProxy(IDatabaseFactory databaseFactory)
:base(databaseFactory)
{ }
public IEnumerable<ScatterPlotModel> GetSavedScatterPlots() {
this.GetValidTargets().Select(t => new ScatterPlotModel{ ... });
}
}
public interface IScatterPlotRepositoryProxy
{
IEnumerable<ScatterPlotModel> GetSavedScatterPlots()
}
请注意这一点是如何从TargetRepository
而不是RepositoryBase<Entity>
继承的。这是因为ScatterPlotModel
不是一个实体,甚至没有持久化。但是,我想要另一层分离,这样我的TargetRespository
就不会混淆所有不同图表类型的方法。
我还没有实际实现过,所以还没有错误。但我预见到我的Autofac DI电话会在以后引起问题所以我提前要求。
如何使用Autofac正确注册这些“存储库代理”?目前我有这个:
builder.RegisterAssemblyTypes(typeof(TargetRepository ).Assembly).Where(t => t.Name.EndsWith("Repository")).AsImplementedInterfaces().InstancePerApiRequest();
添加这个似乎会发生冲突:
builder.RegisterAssemblyTypes(typeof(TargetRepository ).Assembly).Where(t => t.Name.EndsWith("RepositoryProxy")).AsImplementedInterfaces().InstancePerHttpRequest();
我是否会得到我期望的行为(IScatterPlotRepositoryProxy
将解析为ScatterPlotRepositoryProxy
而ITargetRepository
应继续解析为TargetRepository
,尽管ScatterPlotRepositoryProxy
也会从{{1}}实施基础库)?
尝试从程序集中一次性完成所有操作,以避免为每个存储库添加行。
答案 0 :(得分:3)
你错过了系统中的抽象概念。这会给你带来各种各样的麻烦和你已经目睹的痛苦。
您需要的是对系统中查询的常见抽象。这消除了使用自定义存储库接口的需要。诸如ITargetRepository
之类的自定义存储库接口违反了五个SOLID原则中的三个,这毫无疑问会导致各种可维护性问题。
我过去曾写过一篇关于这个主题的文章,所以我不会在这里重复一遍(让我们保留DRY),但你一定要读这篇文章:Meanwhile... on the query side of my architecture。< / p>
在应用该文章中给出的体系结构指南时,使用Autofac注册存储库和查询都没有问题。这只是一个问题:
builder.RegisterAssemblyTypes(typeof(IRepository<>).Assembly)
.AsClosedTypesOf(typeof(IRepository<>));
builder.RegisterAssemblyTypes(typeof(IQueryHandler<,>).Assembly)
.AsClosedTypesOf(typeof(IQueryHandler<,>));