C#设计模式 – 为许多数据源设计的最佳方式
|
参见英文答案 >
How to avoid Dependency Injection constructor madness?????????????????????????????????????9个
我目前有一个ASP.Net MVC 5应用程序,它使用3个外部数据源(调用外部API,响应反序列化,并映射到业务POCO). 该应用程序当前使用SimpleInjector将每个数据源的具体存储库注入业务逻辑层以供使用. 问题是,随着更多的数据源被添加(可能是20-30),构造函数将是巨大的,并且注入所有这些存储库似乎很麻烦. 是否有更好的模式/方法来消耗所有数据源而不是使用不同的存储库? 外观或其他模式会更合适吗? 非常通用的例子: public class MyObject(){
public IEnumerable<Cat> Cats { get; set; }
public IEnumerable<Dog> Dogs { get; set; }
public IEnumerable<Fish> Fish { get; set; }
}
public class BusinessLogic{
private readonly ISourceARepository _sourceA;
private readonly ISourceBRepository _sourceB;
private readonly ISourceCRepository _sourceC;
public BusinessLogic(ISourceARepository sourceA,ISourceBRepository sourceB,ISourceCRepository sourceC){
_sourceA = sourceA;
_sourceB = sourceB;
_sourceC = sourceC;
}
private Dog MapSourceARecordToDog(SourceARecord record){
var result = new Dog();
if(record != null){
result.Name = record.NameField;
result.Age = record.Age;
}
return result;
}
private Cat MapSourceBRecordToCat(SourceBRecord record){
var result = new Cat();
if(record != null){
result.Name = record.NameField;
result.Weight = record.WeightField;
}
return result;
}
private Fish MapSourceCRecordToFish(SourceCRecord record){
var result = new Fish();
if(record != null){
result.ID = record.IDField;
result.Name = record.NameField;
}
return result;
}
public MyObject GetResults(){
var result = new MyObject();
result.Dogs = _sourceA.GetAll().Select(MapSourceARecordToDog).ToList();
result.Cats = _sourceB.GetAll().Select(MapSourceBRecordToCat).ToList();
result.Fish = _sourceC.GetAll().Select(MapSourceCRecordToFish).ToList();
return result;
}
}
public class SourceARespository : ISourceARepository{
public IEnumerable<SourceAResult> GetAll(){
return new List<SourceAResult>();
}
}
public class SourceBRespository : ISourceBRepository{
public IEnumerable<SourceBResult> GetAll(){
return new List<SourceBResult>();
}
}
public class SourceCRespository : ISourceCRepository{
public IEnumerable<SourceCResult> GetAll(){
return new List<SourceCResult>();
}
}
更新: 解决方法
您应该只将每个实体的一个存储库注入依赖于它的使用者.您还可以选择使用业务类中介来修改存储库.
更新: 根据问题和问题陈述中提供的信息,这是一种可能的解决方案.像这样定义您的核心基础架构: public abstract class Entity<TEntity,TDomainObject,TIRepository>
where TEntity : Entity<TEntity,TIRepository>
where TDomainObject : Entity<TEntity,TIRepository>.BaseDomainObject,new()
where TIRepository : Entity<TEntity,TIRepository>.IBaseRepository
{
public class BaseDomainObject {}
public interface IBaseRepository
{
IEnumerable<TDomainObject> GetAll();
IEnumerable<T> GetAllMapped<T>(Func<TDomainObject,T> mapper);
}
public class BaseRepository : IBaseRepository
{
public IEnumerable<TDomainObject> GetAll()
{
return new List<TDomainObject>();
}
public IEnumerable<T> GetAllMapped<T>(Func<TDomainObject,T> mapper)
{
return this.GetAll().Select(mapper);
}
}
}
像这样定义源实体: public class SourceA : Entity<SourceA,SourceA.DomainObject,SourceA.IRepository>
{
public class DomainObject : BaseDomainObject
{
public string Name;
public int Age;
}
public interface IRepository : IBaseRepository {}
public class Repository : BaseRepository,IRepository {}
}
public class SourceB : Entity<SourceB,SourceB.DomainObject,SourceB.IRepository>
{
public class DomainObject : BaseDomainObject
{
public string Name;
public decimal Weight;
}
public interface IRepository : IBaseRepository {}
public class Repository : BaseRepository,IRepository {}
}
public class SourceC : Entity<SourceC,SourceC.DomainObject,SourceC.IRepository>
{
public class DomainObject : BaseDomainObject
{
public Guid Id;
public string Name;
}
public interface IRepository : IBaseRepository {}
public class Repository : BaseRepository,IRepository {}
}
然后像这样定义一个ISourceRepositoryContext接口,并在此处添加每个源存储库接口: public interface ISourceRepositoryContext
{
SourceA.IRepository SourceARepository { get; }
SourceB.IRepository SourceBRepository { get; }
SourceC.IRepository SourceCRepository { get; }
}
然后定义接口的默认实现: public class DefaultSourceRepositoryContext : ISourceRepositoryContext
{
public SourceA.IRepository SourceARepository => new SourceA.Repository();
public SourceB.IRepository SourceBRepository => new SourceB.Repository();
public SourceC.IRepository SourceCRepository => new SourceC.Repository();
}
定义结果传输对象: public class Dog
{
public string Name;
public int Age;
}
public class Cat
{
public string Name;
public decimal Weight;
}
public class Fish
{
public Guid Id;
public string Name;
}
public class MyObject
{
public IEnumerable<Cat> Cats { get; set; }
public IEnumerable<Dog> Dogs { get; set; }
public IEnumerable<Fish> Fish { get; set; }
}
然后使用BusinessLogic类中的ISourceRepositoryContext: public class BusinessLogic
{
protected ISourceRepositoryContext repositories;
public BusinessLogic(ISourceRepositoryContext repositories)
{
this.repositories = repositories;
}
public MyObject GetResults(string param1)
{
return new MyObject()
{
Dogs = this.repositories.SourceARepository.GetAllMapped
(domainObject=>new Dog
{
Age = domainObject.Age,Name = domainObject.Name
}),Cats = this.repositories.SourceBRepository.GetAllMapped
(domainObject=>new Cat
{
Name = domainObject.Name,Weight = domainObject.Weight
}),Fish = this.repositories.SourceCRepository.GetAllMapped
(domainObject=>new Fish
{
Id = domainObject.Id,};
}
}
我已经确认以上编译在C#6.0下. 我建议将IRepository更改为实体中的IBusiness,并将数据访问问题分解为IDataAccess接口,只有IBusiness实现者通过其构造函数接收.然后将ISourceRepositoryContext更改为ISourceEntities,并将该接口中的IRepository属性更改为IBusiness属性. BusinessLogic类是我真正关心的部分.你确定这一课不会引起太多关注吗?这应该是UoW课吗? 有关基于类似技术的更完整解决方案,请查看我对其他问题的回答:.NET Managing Layers Relationships (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
