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 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |