C# 从Mongo读取数据时发送IRepository模型依赖项

C# 从Mongo读取数据时发送IRepository模型依赖项,c#,mongodb,dependency-injection,domain-driven-design,autofac,C#,Mongodb,Dependency Injection,Domain Driven Design,Autofac,在我的应用程序中,我使用Autofac ContainerBuilder注册我的存储库 我还有一个CustomerModel类,它表示MongoDB集合。它还对其他域模型具有正向依赖性: public class CustomerModel { private readonly IRepository<OrderModel> _ordeRepository; public CustomerModel(IRepository<OrderModel> ord

在我的应用程序中,我使用Autofac ContainerBuilder注册我的存储库

我还有一个CustomerModel类,它表示MongoDB集合。它还对其他域模型具有正向依赖性:

public class CustomerModel
{
    private readonly IRepository<OrderModel> _ordeRepository;

    public CustomerModel(IRepository<OrderModel> ordeRepository)
    {
        _ordeRepository = ordeRepository;
    }

    [BsonId]
    public ObjectId Id;

    public string Email;

    ...

    public List<OrderModel> Orders
    {
        get { return _ordeRepository.List(x => x.CustomerId == Id); }
    }
}
公共类CustomerModel
{
私有只读存储库_ordeRepository;
公共客户模型(IRepository OrderDepository)
{
_ordeRepository=ordeRepository;
}
[BsonId]
公共对象Id;
公共字符串电子邮件;
...
公开名单命令
{
获取{return _ordeRepository.List(x=>x.CustomerId==Id);}
}
}
从Mongo读取数据时,如何注入IRepository依赖关系

public interface IRepository<TEntity>
{
    IList<TEntity> List(Expression<Func<TEntity, bool>> expression);
}

public class MongoRepository<TEntity> : IRepository<TEntity>
{
    public IList<TEntity> List(Expression<Func<TEntity, bool>> expression)
    {
        IMongoCollection<TEntity> collection = ...;
        return collection.FindSync(expression).ToList();
    }
}
公共接口IRepository
{
IList列表(表达式);
}
公共类MongoRepository:IRepository
{
公共IList列表(表达式)
{
IMongoCollection集合=。。。;
return collection.FindSync(expression.ToList();
}
}

您不应该让实现与您的属性直接关联。原因是,实体是数据的表示,实体不关心项目的存储或创建方式。只是业务对象的表示

另一个问题是,根据Martin Fowler和Evans的定义,您违反了遵循领域驱动设计的更常见实践。最大的违规之一是,您在一个属性中强制使用逻辑,如果您调用该属性,则会自动访问数据库

正如C#深度作者所指出的:

<>对于你所写的每种类型,你应该考虑它的接口 世界其他地区(包括同一程序集中的类)。这 是它对它所提供的东西的描述,它的外在角色。 实现不应该是描述的一部分,也不应该是描述的一部分 绝对是的。(这就是为什么我更喜欢构图而不是继承, 选择有意义的地方——继承通常会暴露或限制 可能的实现。)

物业传达了“我将为客户提供价值”的理念 “这不是一个实现概念, 这是一个界面概念。另一方面,一个字段进行通信 实现——它说“这个类型代表这个类型中的一个值 非常具体的方式”。没有封装,这是裸存储 格式。这是字段不属于接口的部分原因- 他们不属于那里,因为他们谈论如何取得成就 而不是所取得的成就

我非常同意,很多时候,字段实际上可以被使用 在应用程序的生命周期中没有问题。只是不清楚 这些时间都是预先设定的,但它仍然违反了设计 不公开实现的原则

在遵循设计原则的同时处理实现可能更适合以下方法和/或体系结构风格。请记住,模式不是饼干切割器。他们为特定的原因解决特定的问题,他们引入自身的复杂性和问题。您必须根据您的应用权衡解决方案的优点

// Repositories:
public interface ICustomerRepository : IDisposable
{
     IEnumerable<CustomerModel> RetrieveAllCustomers();

     CustomerModel RetrieveCustomerWithOrders(int id);
}

// Context:
public class CustomerContext : ICustomerRepository
{
     private bool disposed = false;
     private readonly IDbConnection dbConnection;

     public CustomerContext(IConfiguration configuration) => dbConnection = configuration.GetConnectionString("dbConnection");

     public IEnumerable<CustomerModel> RetrieveAllCustomers() => dbConnection.Query<CustomerModel>(query);

     public CustomerModel RetrieveCustomerWithOrders(int id) => dbConnection.Query<CustomerModel, OrderModel, CustomerModel>(query, (customer, order) =>
     {
          customer.Orders = order;
          return customer;
     }, new { CustomerId = id });

     public virtual bool Dispose(bool disposing)
     {
         if(!disposed)
         {
              if(disposing)
                  dbConnection.Dispose();

              disposed = true;
         }
     }

     public void Dispose() 
     {
          Dispose(true);
          GC.SuppressFinalize(this);
     }

     ~CustomerContext() => Dispose(true);     
}

// Factory:
public class CustomerFactory : ICustomerFactory
{
     private readonly IConfiguration configuration;

     public CustomerFactory(IConfiguration configuration) => this.configuration = configuration;

     public ICustomerRepository InstantiateCustomer() => new CustomerContext(configuration);
}

public interface ICustomerFactory
{
     ICustomerRepository InstantiateCustomer();
}
//存储库:
公共接口ICCustomerRepository:IDisposable
{
IEnumerable RetrieveAllCustomers();
CustomerModel RetrieveCustomerWithOrders(int id);
}
//背景:
公共类CustomerContext:ICCustomerRepository
{
私有布尔=假;
专用只读IDbConnection dbConnection;
公共CustomerContext(IConfiguration配置)=>dbConnection=configuration.GetConnectionString(“dbConnection”);
public IEnumerable RetrieveAllCustomers()=>dbConnection.Query(查询);
公共CustomerModel RetrieveCustomerWithOrders(int id)=>dbConnection.Query(查询,(客户,订单)=>
{
客户订单=订单;
退货客户;
},新的{CustomerId=id});
公共虚拟bool Dispose(bool disposing)
{
如果(!已处置)
{
如果(处置)
dbConnection.Dispose();
这是真的;
}
}
公共空间处置()
{
处置(真实);
总干事(本);
}
~CustomerContext()=>Dispose(true);
}
//工厂:
公共类CustomerFactory:ICCustomerFactory
{
专用只读IConfiguration配置;
公共CustomerFactory(IConfiguration配置)=>this.configuration=configuration;
公共ICCustomerRepository instanceCustomer()=>新的CustomerContext(配置);
}
公共接口ICustomerFactory
{
icCustomerRepository实例化ecustomer();
}
因此,我们创建了一些抽象,我们构建了我们的容器,我们与适当的实现有明确的契约。因此,如果有人现在要使用您构建的内容,它将如下所示:

public class CustomerService
{
     private readonly ICustomerFactory customerFactory;
     private readonly IConfiguration configuration;

     public CustomerService(ICustomerFactory customerFactory, IConfiguration configuration)
     {
          this.customerFactory = customerFactory;
          this.configuration = configuration;
     }

     public IEnumerable<CustomerModel> GetAllCustomers()
     {
         using(var customerContext = customerFactory.InstantiateCustomer(configuration))
              return customerContext.RetrieveAllCustomers();
     }

     public CustomerModel GetCustomerOrders(CustomerModel customer)
     {
          using(var customerContext = customerFactory.InstantiateCustomer(configuration))
              return customerContext.RetrieveCustomerWithOrders(customer.Id);
     }
}
公共类客户服务
{
私有只读ICCustomerFactory customerFactory;
专用只读IConfiguration配置;
公共CustomerService(ICCustomerFactory customerFactory,IConfiguration配置)
{
this.customerFactory=customerFactory;
this.configuration=配置;
}
公共IEnumerable GetAllCustomers()
{
使用(var customerContext=customerFactory.instanceCustomer(配置))
返回customerContext.RetrieveAllCustomers();
}
公共CustomerModel GetCustomerOrders(CustomerModel客户)
{
使用(var customerContext=customerFactory.instanceCustomer(配置))
返回customerContext.RetrieveCustomerWithOrders(customer.Id);
}
}
因此,当它们与您的服务实现交互时,它将创建清晰性,但也将允许清晰、简洁和表达性的代码流。实现者可以清楚地看到服务imp中发生了什么