我目前有一个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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。