Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#设计模式-设计许多数据源的最佳方式_C#_Asp.net_Asp.net Mvc_Design Patterns - Fatal编程技术网

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

C#设计模式-设计许多数据源的最佳方式,c#,asp.net,asp.net-mvc,design-patterns,C#,Asp.net,Asp.net Mvc,Design Patterns,我目前有一个ASP.NETMVC5应用程序,它使用3个外部数据源(调用外部API,反序列化响应,并映射到业务POCO) 该应用程序目前使用SimpleInjector将每个数据源的具体存储库注入业务逻辑层以供使用 问题是,随着更多数据源的添加(可能是20-30个),构造函数将变得庞大,注入所有这些存储库似乎很麻烦 是否有更好的模式/方法来使用所有数据源而不是使用不同的存储库 正面或其他样式更合适吗 非常一般的例子: public class MyObject(){ pu

我目前有一个ASP.NETMVC5应用程序,它使用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>();
             }
         }
公共类MyObject(){
公共IEnumerable猫{get;set;}
公共IEnumerable狗{get;set;}
公共IEnumerable Fish{get;set;}
}
公共类业务逻辑{
私有只读的ISourceARepository\u sourceA;
私有只读源存储库;
私有只读isosourcerepository\u sourceC;
公共业务逻辑(ISOURCERepository源A、ISourceBRepository源B、ISOURCERepository源C){
_sourceA=sourceA;
_sourceB=sourceB;
_sourceC=sourceC;
}
私家犬地图源ARECORDTODOG(源ARECORD记录){
var结果=新狗();
if(记录!=null){
result.Name=record.NameField;
结果.年龄=记录.年龄;
}     
返回结果;
}
专用Cat映射SourceBrecordtocat(SourceBRecord记录){
var结果=新的Cat();
if(记录!=null){
result.Name=record.NameField;
result.Weight=record.WeightField;
}
返回结果;
}
私人鱼类地图SourceCrecordtofish(SourceCRecord记录){
var结果=新的Fish();
if(记录!=null){
result.ID=record.IDField;
result.Name=record.NameField;
}
返回结果;
}
公共MyObject GetResults(){
var结果=新的MyObject();
result.Dogs=_sourceA.GetAll().Select(mapsourcearecordtolog.ToList();
result.Cats=_sourceB.GetAll().Select(MapSourceBRecordToCat.ToList();
result.Fish=\u sourceC.GetAll().Select(MapSourceCRecordToFish.ToList();
返回结果;
}
}
公共类源位置:Isourcerepository{
公共IEnumerable GetAll(){
返回新列表();
}
}
公共类SourceBRespository:IsourceBrepPository{
公共IEnumerable GetAll(){
返回新列表();
}
}
公共类源位置:IsourceRepository{
公共IEnumerable GetAll(){
返回新列表();
}
}
更新:
这不是构造函数疯狂问题的重复,因为在这个场景中,一个类需要许多不同的数据源,但仍然有单一的责任。因此,它保证了自己的解释和答案。

每个实体只应向依赖它的使用者注入一个存储库。您还可以选择使用业务类中介来调整存储库

更新

根据问题和问题陈述中提供的信息,这里有一个可能的解决方案。按照以下方式定义您的核心基础架构:

public abstract class Entity<TEntity, TDomainObject, TIRepository>
    where TEntity       : Entity<TEntity, TDomainObject, TIRepository>
    where TDomainObject : Entity<TEntity, TDomainObject, TIRepository>.BaseDomainObject, new()
    where TIRepository  : Entity<TEntity, TDomainObject, 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 {}
}
然后定义接口的默认实现:

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; }
}
我已经确认上面的代码是在C#6.0下编译的

我建议将IRepository更改为实体中的IBusiness,并将数据访问问题从拆分为IDataAccess接口,只有IBusiness实现者通过其构造函数接收该接口。然后将ISourceRepositoryContext更改为ISourceEntities,并将该接口中的IRepository属性改为IBusiness属性

BusinessLogic类是我真正关心的部分。你确定这门课不会有太多的顾虑吗?这应该是UoW课程吗


要获得基于类似技术的更完整的解决方案,请查看我对另一个问题的回答:

具体的存储库是什么样子的?您能给出这样一个实现的示例吗?添加了一个通用示例。您是否需要在业务对象中同时使用所有三种类型的存储库?我不确定SimpleInjector是否允许属性注入。这将为您解决一个负担。@user2966445我很乐意详细说明,但首先您可以为MyObject、SourceAResult、SourceBResult和SourceCResult提供类定义。您真的需要BusinessLogic类的所有200个源吗?或者BusinessLogic打算成为某种基类?@user2966445一般来说,如果您向一个类中添加了3-5个以上的依赖项,通常会被认为是一种代码气味,可能表明您的类承担了太多的责任。你可能想考虑重构它。谢谢,但我正在寻找一个实际的替代品。我意识到有一个问题(因此提出了这个问题)。这个例子应该提供足够的信息来理解这个概念。随着更多数据源的添加,构造函数会增长。@user2966445不幸的是,该示例没有提供足够的关于MyObject如何与SourceAResult、SourceBResult和SourceCResult关联的信息。如果没有这些信息,就很难分析您的情况并提出建议alternative@user2966445我已经更新了我的答案,希望它能为您提供一个解决方案,或者至少给您一些关于如何重构代码的想法。
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; }
}
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,
                Name    = domainObject.Name
            }),
        };
    }
}