Mee*_*eep 3 c# domain-driven-design object
所以.这可能是一个愚蠢的问题,但......
我只限于使用不支持EntityFramework的数据库,但我仍然希望将我的数据层分离到一个单独的程序集中.这意味着我需要共享域对象值,同时避免业务和数据层之间的循环引用.因此,我想知道构建一个持久性接口存储库是否可以接受,该存储库可以由业务层实现并相互独立地传递给数据层.
示例如下:
// Business Layer
public class Customer: IPersistableCustomer
{
private string name;
public string Name{ get { return this.name; } }
public void persist()
{
dataLayer.StoreCustomerInstance(this);
}
}
// DataLayer
public StoreCustomerInstance(IPersistableCustomer persistableCustomer)
{
// Do storage stuff
}
// Interface repository
public interface IPersistableCustomer
{
string Name { get; }
}
Run Code Online (Sandbox Code Playgroud)
我几乎可以肯定这是一个可怕的想法,但我不确定为什么.我有兴趣了解人们的想法,看看哪里有潜在的陷阱.
您在示例中所做的是在界面后隐藏域对象.你应该做的是隐藏你的数据层在接口后面.这种数据层抽象通常称为存储库模式.
在业务层中,您可以定义域类和存储库接口:
public class Customer
{
public Customer(string name)
{
this.Name = name;
}
public string Name { get; private set; }
}
public interface ICustomerRepository
{
void Save(Customer customer);
}
Run Code Online (Sandbox Code Playgroud)
请注意,Customer类没有任何持久性逻辑.存储库接口也没有; 它只定义数据层的合约.
合同的实施在数据层:
public class SqlCustomerRepository : ICustomerRepository
{
public void Save(Customer customer)
{
// Persistence logic
}
}
Run Code Online (Sandbox Code Playgroud)
此时,数据层需要对业务层的引用,而不是相反.
您可以在应用程序层中将这两个层绑定在一起:
class CustomerForm
{
private readonly ICustomerRepository customerRepository;
// This class declares a dependency on any ICustomerRepository
public CustomerForm(ICustomerRepository customerRepository)
{
this.customerRepository = customerRepository;
}
public void PersistCustomer()
{
Customer customer = CreateCustomerFromUserInput();
this.customerRepository.Save(customer);
}
}
class Program
{
static void Main(string[] args)
{
// Dependency injection, usually done via a DI container
var customerRepository = new SqlCustomerRepository();
var form = new CustomerForm(customerRepository);
form.PersistCustomer();
}
}
Run Code Online (Sandbox Code Playgroud)
当我遇到与你相同的问题时,我发现洋葱建筑上的文章非常有价值.它解释了如何以防止与数据层紧密耦合的方式设置应用程序的体系结构.
使用数据层接口的另一个好处是,它允许您对大部分代码进行单元测试,而无需运行实际的数据库.您只需模拟存储库接口即可.
几年前我曾经为我的域对象使用过接口.我不后悔,因为它告诉我如何不这样做.但这是唯一的好事; 这是一项额外的工作和维护,没有任何实际的好处:)
| 归档时间: |
|
| 查看次数: |
1570 次 |
| 最近记录: |