DDD:管理“工作單元實例”的兩種模式


概念介紹

類圖如下:

在常見的用例場景下,類圖的對象圖如下:

問題

在一個用例執行過程中,如何保證同一個界限上下文內的所有倉儲實例可以共享同一個工作單元實例?

解決方案1

 倉儲采用依賴注入模式 + 使用IOC管理工作單元的生命周期(PerRequest或其它)。

代碼示例

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 using Autofac;
 8 
 9 namespace AutoFacStudy
10 {
11     class Program
12     {
13         static void Main(string[] args)
14         {
15             var buider = new ContainerBuilder();
16             buider.RegisterType<服務>();
17             buider.RegisterType<倉儲A>();
18             buider.RegisterType<倉儲B>();
19             buider.RegisterType<工作單元>().InstancePerLifetimeScope();
20 
21             var container = buider.Build();
22 
23             dynamic 服務 = container.Resolve<服務>();
24 
25             //下邊兩行代碼輸出一樣
26             Console.WriteLine(服務.倉儲A.工作單元.GetHashCode());
27             Console.WriteLine(服務.倉儲B.工作單元.GetHashCode());
28         }
29     }
30 
31     public class 服務
32     {
33         private readonly 倉儲A _倉儲A;
34         private readonly 倉儲B _倉儲B;
35 
36         public 服務(倉儲A 倉儲A, 倉儲B 倉儲B)
37         {
38             _倉儲A = 倉儲A;
39             _倉儲B = 倉儲B;
40         }
41 
42         public 倉儲A 倉儲A
43         {
44             get { return _倉儲A; }
45         }
46 
47         public 倉儲B 倉儲B
48         {
49             get { return _倉儲B; }
50         }
51     }
52 
53     public class 工作單元 { }
54 
55     public class 倉儲A
56     {
57         private readonly 工作單元 _工作單元;
58 
59         public 倉儲A(工作單元 工作單元)
60         {
61             _工作單元 = 工作單元;
62         }
63 
64         public 工作單元 工作單元
65         {
66             get { return _工作單元; }
67         }
68     }
69 
70     public class 倉儲B
71     {
72         private readonly 工作單元 _工作單元;
73 
74         public 倉儲B(工作單元 工作單元)
75         {
76             _工作單元 = 工作單元;
77         }
78 
79         public 工作單元 工作單元
80         {
81             get { return _工作單元; }
82         }
83     }
84 }

解決方案2

 倉儲采用服務定位器模式 + 使用服務定位器或簡單工廠管理工作單元的生命周期(PerRequest或其它)。

代碼示例

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 using Autofac;
 8 
 9 namespace AutoFacStudy
10 {
11     class Program
12     {
13         public static IContainer 服務定位器;
14 
15         static void Main(string[] args)
16         {
17             var buider = new ContainerBuilder();
18             buider.RegisterType<服務>();
19             buider.RegisterType<倉儲A>();
20             buider.RegisterType<倉儲B>();
21             buider.RegisterType<工作單元>().InstancePerLifetimeScope();
22 
23             服務定位器 = buider.Build();
24 
25             dynamic 服務 = 服務定位器.Resolve<服務>();
26 
27             //下邊兩行代碼輸出一樣
28             Console.WriteLine(服務.倉儲A.工作單元.GetHashCode());
29             Console.WriteLine(服務.倉儲B.工作單元.GetHashCode());
30         }
31     }
32 
33     public class 服務
34     {
35         private readonly 倉儲A _倉儲A;
36         private readonly 倉儲B _倉儲B;
37 
38         public 服務(倉儲A 倉儲A, 倉儲B 倉儲B)
39         {
40             _倉儲A = 倉儲A;
41             _倉儲B = 倉儲B;
42         }
43 
44         public 倉儲A 倉儲A
45         {
46             get { return _倉儲A; }
47         }
48 
49         public 倉儲B 倉儲B
50         {
51             get { return _倉儲B; }
52         }
53     }
54 
55     public class 工作單元 { }
56 
57     public class 倉儲A
58     {
59         private readonly 工作單元 _工作單元;
60 
61         public 倉儲A()
62         {
63             _工作單元 = Program.服務定位器.Resolve<工作單元>();
64         }
65 
66         public 工作單元 工作單元
67         {
68             get { return _工作單元; }
69         }
70     }
71 
72     public class 倉儲B
73     {
74         private readonly 工作單元 _工作單元;
75 
76         public 倉儲B()
77         {
78             _工作單元 = Program.服務定位器.Resolve<工作單元>();
79         }
80 
81         public 工作單元 工作單元
82         {
83             get { return _工作單元; }
84         }
85     }
86 }

由此示例可以看出,服務定位器和依賴注入可以混合在一起使用。這個例子我為了簡單,服務定位器和IOC容器是同一個實例。

有些系統將服務定位器的實現換成簡單工廠模式,他們本質上是一樣的(服務定位器是一個萬能工廠)。

代碼示例

 1 public class 工作單元工廠
 2 {
 3     public static 工作單元 創建()
 4     {
 5         var 工作單元 = (工作單元)CallContext.GetData("工作單元");
 6 
 7         if (工作單元 == null)
 8         {
 9             工作單元 = new 工作單元();
10             CallContext.SetData("工作單元", 工作單元);
11         }
12 
13         return 工作單元;
14     }
15 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM