在我的应用中,我使用Autofac ContainerBuilder来注册我的存储库...
我还有一个CustomerModel类,它代表MongoDB集合。它还对其他域模型具有IRepository依赖项:
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); }
}
}
从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();
}
}
答案 0 :(得分:2)
您不应将实现直接与您的媒体资源相关联。原因是,实体代表您的数据,但实体并不关心项目的存储或创建方式。只是您的业务对象的表示。
另一个问题是,按照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();
}
因此,我们已经创建了一些抽象,已经构建了容器,并且已经有了具有适当实现的明确合同。因此,如果有人现在要使用您所构建的内容,它将类似于以下内容:
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);
}
}
因此,当它们与您的服务实现交互时,将创建清晰度,但也将允许清晰,简洁和富于表现力的代码流。实现者可以清楚地看到服务实现中发生了什么,但是完全不了解数据实现是如何发生的。
我没有添加任何错误处理或null检查,但希望能对您有所帮助。