关于DDD:管理"工作单元实例"的两种模式的使用方法

图如下:

在常见的用例场景下,类图的对象图如下:

问题在一个用例执行过程中,如何保证同一个界限上下文内的所有仓储实例可以共享同一个工作单元实例?解决方案1 
仓储采用依赖注入模式 + 使用IOC管理工作单元的生命周期(PerRequest或其它)。

代码示例


代码如下:

using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;

using Autofac;

namespace AutoFacStudy
 {
     class Program
     {
         static void Main(string[] args)
         {
             var buider = new ContainerBuilder();
             buider.RegisterType<服务>();
             buider.RegisterType<仓储A>();
             buider.RegisterType<仓储B>();
             buider.RegisterType<工作单元>().InstancePerLifetimeScope();

var container = buider.Build();

dynamic 服务 = container.Resolve<服务>();

//下边两行代码输出一样
             Console.WriteLine(服务.仓储A.工作单元.GetHashCode());
             Console.WriteLine(服务.仓储B.工作单元.GetHashCode());
         }
     }

public class 服务
     {
         private readonly 仓储A _仓储A;
         private readonly 仓储B _仓储B;

public 服务(仓储A 仓储A, 仓储B 仓储B)
         {
             _仓储A = 仓储A;
             _仓储B = 仓储B;
         }

public 仓储A 仓储A
         {
             get { return _仓储A; }
         }

public 仓储B 仓储B
         {
             get { return _仓储B; }
         }
     }

public class 工作单元 { }

public class 仓储A
     {
         private readonly 工作单元 _工作单元;

public 仓储A(工作单元 工作单元)
         {
             _工作单元 = 工作单元;
         }

public 工作单元 工作单元
         {
             get { return _工作单元; }
         }
     }

public class 仓储B
     {
         private readonly 工作单元 _工作单元;

public 仓储B(工作单元 工作单元)
         {
             _工作单元 = 工作单元;
         }

public 工作单元 工作单元
         {
             get { return _工作单元; }
         }
     }
 }

解决方案2
仓储采用服务定位器模式 + 使用服务定位器或简单工厂管理工作单元的生命周期(PerRequest或其它)。
代码示例


代码如下:

using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;

using Autofac;

namespace AutoFacStudy
 {
     class Program
     {
         public static IContainer 服务定位器;

static void Main(string[] args)
         {
             var buider = new ContainerBuilder();
             buider.RegisterType<服务>();
             buider.RegisterType<仓储A>();
             buider.RegisterType<仓储B>();
             buider.RegisterType<工作单元>().InstancePerLifetimeScope();

服务定位器 = buider.Build();

dynamic 服务 = 服务定位器.Resolve<服务>();

//下边两行代码输出一样
             Console.WriteLine(服务.仓储A.工作单元.GetHashCode());
             Console.WriteLine(服务.仓储B.工作单元.GetHashCode());
         }
     }

public class 服务
     {
         private readonly 仓储A _仓储A;
         private readonly 仓储B _仓储B;

public 服务(仓储A 仓储A, 仓储B 仓储B)
         {
             _仓储A = 仓储A;
             _仓储B = 仓储B;
         }

public 仓储A 仓储A
         {
             get { return _仓储A; }
         }

public 仓储B 仓储B
         {
             get { return _仓储B; }
         }
     }

public class 工作单元 { }

public class 仓储A
     {
         private readonly 工作单元 _工作单元;

public 仓储A()
         {
             _工作单元 = Program.服务定位器.Resolve<工作单元>();
         }

public 工作单元 工作单元
         {
             get { return _工作单元; }
         }
     }

public class 仓储B
     {
         private readonly 工作单元 _工作单元;

public 仓储B()
         {
             _工作单元 = Program.服务定位器.Resolve<工作单元>();
         }

public 工作单元 工作单元
         {
             get { return _工作单元; }
         }
     }
 }

由此示例可以看出,服务定位器和依赖注入可以混合在一起使用。这个例子我为了简单,服务定位器和IOC容器是同一个实例。

有些系统将服务定位器的实现换成简单工厂模式,他们本质上是一样的(服务定位器是一个万能工厂)。

代码示例


代码如下:

public class 工作单元工厂
 {
     public static 工作单元 创建()
     {
         var 工作单元 = (工作单元)CallContext.GetData("工作单元");

if (工作单元 == null)
         {
             工作单元 = new 工作单元();
             CallContext.SetData("工作单元", 工作单元);
         }

return 工作单元;
     }
 }

(0)

相关推荐

  • 关于DDD:管理"工作单元实例"的两种模式的使用方法

    图如下: 在常见的用例场景下,类图的对象图如下: 问题在一个用例执行过程中,如何保证同一个界限上下文内的所有仓储实例可以共享同一个工作单元实例?解决方案1 仓储采用依赖注入模式 + 使用IOC管理工作单元的生命周期(PerRequest或其它). 代码示例 复制代码 代码如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.T

  • PHP面向对象之工作单元(实例讲解)

    工作单元 这个模式涉及到了领域模型.数据映射器和标识映射,这里就统一进行整理和回顾了. $venue = new \woo\domain\Venue(null,"The Green Tree"); \woo\domain\ObjectWatcher::instance()->performOperations(); 现在以上面的二行客户端代码为切入点大概的叙述一下这个模式是怎么工作的. 第一句在使用领域模型对象创建一个对象的时候,它就调用了标识映射ObjectWatcher类 将

  • JS实现星星评分功能实例代码(两种方法)

    一.方法1 1.用到图片 2.结构和样式 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> ul { padding-left: 0; overflow: hidden; } ul li { float: left; list-style: no

  • vue前端路由以及vue-router两种模式实例详解

    目录 前言 1.什么是前端路由 (1)后端路由阶段 (2)前后端分离路由阶段 (3)单页面应用阶段 2.vue-router提供了hash和history两种路由模式 (1)hash模式 (2)history模式 (3)两种模式的比较 补充:路由模式解析 总结 前言 路由这个概念最早在后端出现,随后前后端分离,直至当今的单页面应用,路由也在一直发生变化.本文来总结一下路由变化和vue-router中的路由模式区别相关知识点. 1.什么是前端路由 (1)后端路由阶段 早期的页面都是由html页面在

  • vue-router两种模式区别及使用注意事项详解

    本文实例讲述了vue-router两种模式区别及使用注意事项.分享给大家供大家参考,具体如下: Vue Router 是Vue官方的路由管理器.它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌.vue-router 默认 hash 模式,还有一种是history模式. hash模式 hash模式的工作原理是hashchange事件,可以在window监听hash的变化.我们在url后面随便添加一个#xx触发这个事件. window.onhashchange = function(

  • Javascript里的两种使用正则的方法

    在Javascript里,有两种使用正则的方法,一是创建一个正则表达式的实例,而是使用String对象里的正则表达相关的方法. 正则表达式对象 两种创建方法 var my_regex=/[a-z]+/g;  var my_regex=new ("[a-z]+","g"); 方法 exec(string),对string进行正则处理,并返回匹配结果.  test(string),测试string是否含有匹配结果 字符串对象中的正则 方法 match(pattern) 

  • golang两种调用rpc的方法

    本文实例讲述了golang两种调用rpc的方法.分享给大家供大家参考,具体如下: golang的rpc有两种方法进行调用,一种是rpc例子中给的: 复制代码 代码如下: package main import (         "net/rpc"         "net/http"         "log"         "net"         "time" ) type Args struct

  • ThinkPHP中Widget扩展的两种写法及调用方法详解

    本文实例讲述了ThinkPHP中Widget扩展的两种写法及调用方法.分享给大家供大家参考,具体如下: Widget扩展一般用于页面组件的扩展,在页面根据需要输出不同的内容,下面介绍一下ThinkPHP中Widget的两种写法及调用 写法一: ArticlWidget.class.php文件: class ArticleWidget extends Widget { /** * * @param array $data * @return type * 调用方法:{:W('ArticleList

  • vue-router的两种模式的区别

    1.大家都知道vue是一种单页应用,单页应用就是仅在页面初始化的时候加载相应的html/css/js一单页面加载完成,不会因为用户的操作而进行页面的重新加载或者跳转,用javascript动态的变化html的内容 优点: 良好的交互体验,用户不需要刷新页面,页面显示流畅, 良好的前后端工作分离模式,减轻服务器压力, 缺点: 不利于SEO,初次加载耗时比较多 2.hash模式 vue-router默认的是hash模式-使用URL的hash来模拟一个完整的URL,于是当URL改变的时候,页面不会重新

  • 浅析vue-router实现原理及两种模式

    之前用Vue开发单页应用,发现不管路由怎么变化,浏览器地址栏总是会有一个'#'号. 当时检查自己的代码,没有发现请求的地址带'#',当时也很纳闷,但是由于没有影响页面的渲染以及向后台发送请求,当时也没有在意.最近看了一下vue-router的实现原理,才逐渐揭开了这个谜题. vue-router 的两种方式(浏览器环境下) 1. Hash (对应HashHistory) hash("#")符号的本来作用是加在URL中指示网页中的位置: http://www.example.com/in

随机推荐