从结构上看,tlibcqrs项目并不复杂,但对其进行介绍,的确让我感到有点无从着手。还是先从领域模型中的对象的行为和状态谈起吧。
先来谈谈对象状态。据我理解,状态就是一种数据,它用来描述,在某个特定的时间上,这个对象所具有的特质,它将作为对象行为发生的依据和结果。我们平时做设计和编程的时候,尤其是在做数据访问层的时候,特别喜欢一些仅仅包含getter/setter属性的对象,以便调用方能够通过getter获得对象的状态,使用setter设置对象的状态。之前我也说明过,状态并非getter/setter属性,在OOP上,状态表现为“字段”(fields)。现在我们讨论的不是数据访问层的DAO,而是领域模型中的实体。当然,实体也是对象,自然也有状态,不仅仅是状态,实体是参与业务逻辑的重要对象,它还有处理业务逻辑的行为。
现在假设我们有个实体为Customer,它同时也是某个聚合的聚合根,在通常情况下,我们会用下面的形式去定义这个Customer实体(为了简化,省去了对象行为):
当然你不会觉得这样设计有什么太大的问题,事实上在我们平时的开发中,也的确是这么做的,而且非CQRS架构的DDD实践也支持这样的实体模型。于是,我们可以使用下面的代码来更新某个Customer的姓名:
1: [TestMethod]
2: public void ChangeCustomerNameTest()
3: {
4: Customer customer = new Customer
5: {
6: Birth = DateTime.Now.AddYears(-20),
7: Email = "daxnet@live.com",
8: FirstName = "dax",
9: LastName = "net",
10: Password = "123456",
11: Username = "daxnet"
12: };
13: using (IRepositoryContext ctx = ObjectContainer.Instance.GetService<IRepositoryContext>())
14: {
15: IRepository<Customer> customerRepository = ctx.GetRepository<Customer>();
16: customerRepository.Add(customer);
17: }
18: ISpecification<Customer> spec = Specification<Customer>.Eval(p => p.Username.Equals("daxnet"));
19: using (IRepositoryContext ctx = ObjectContainer.Instance.GetService<IRepositoryContext>())
20: {
21: IRepository<Customer> customerRepository = ctx.GetRepository<Customer>();
22: var customer2 = customerRepository.Get(spec);
23: Assert.AreEqual(customer.Username, customer2.Username);
24:
25: customer2.FirstName = "qingyang";
26: customer2.LastName =