加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C#设计模式 – 为许多数据源设计的最佳方式

发布时间:2020-12-15 22:17:46 所属栏目:百科 来源:网络整理
导读:参见英文答案 How to avoid Dependency Injection constructor madness?????????????????????????????????????9个 我目前有一个ASP.Net MVC 5应用程序,它使用3个外部数据源(调用外部API,响应反序列化,并映射到业务POCO). 该应用程序当前使用SimpleInjector将
参见英文答案 > 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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读