· 5 years ago · Jul 19, 2020, 06:26 PM
1using Deventure.BusinessLogic.Workflow;
2using Deventure.DataLayer.Repositories;
3using System;
4using System.Collections.Generic;
5
6namespace UpWorky.BusinessLogic.ModelCore
7{
8 internal class RepoContextBase : IDisposable
9 {
10 private RepoUnitOfWork mUnitOfWork;
11
12 private IDictionary<Guid, BaseDataRepository> ActiveRepositories;
13
14 public RepoUnitOfWork UnitOfWork => mUnitOfWork;
15
16 public T GetRepo<T>()
17 where T : BaseDataRepository, new()
18 {
19 if (!ActiveRepositories.ContainsKey(typeof(T).GUID))
20 {
21 T newRepo = mUnitOfWork.Repository<T>();
22
23 ActiveRepositories.Add(typeof(T).GUID, newRepo);
24
25 return newRepo;
26 }
27
28 return (T)ActiveRepositories[typeof(T).GUID];
29 }
30
31 public T GetTrackingRepo<T>()
32 where T : BaseDataRepository, new()
33 {
34 if (!ActiveRepositories.ContainsKey(typeof(T).GUID))
35 {
36 T newRepo = mUnitOfWork.TrackingRepository<T>();
37
38 ActiveRepositories.Add(typeof(T).GUID, newRepo);
39
40 return newRepo;
41 }
42
43 return (T)ActiveRepositories[typeof(T).GUID];
44 }
45
46 public void Dispose()
47 {
48 if (mUnitOfWork != null)
49 {
50 foreach (var key in ActiveRepositories.Keys)
51 {
52 ActiveRepositories[key].Dispose();
53 }
54
55 ActiveRepositories.Clear();
56
57 mUnitOfWork.Dispose();
58 mUnitOfWork = null;
59 }
60 }
61
62 public RepoContextBase()
63 {
64 mUnitOfWork = RepoUnitOfWork.New();
65 ActiveRepositories = new Dictionary<Guid, BaseDataRepository>();
66 }
67 }
68
69 public class RepoContext : IDisposable
70 {
71 #region MEMBER DATA
72
73 private int Level = 0;
74
75 private RepoContextBase mInstance;
76
77 private RepoContextBase Instance => mInstance;
78
79 private bool mEnableChildren = false;
80
81 /// <summary>
82 /// If true child contexts RollbackTransaction() / CommitTransaction() calls will be valid.
83 /// </summary>
84 private bool IsEnableChildren => mEnableChildren;
85
86 public RepoUnitOfWork UnitOfWork => mInstance.UnitOfWork;
87
88 #endregion
89
90 #region PUBLIC API
91
92 /// <summary>
93 /// -> Gets or creates a new T repository <br/>
94 /// -> Once created, the repo instance will "exist" until the [RepoContext] instance is Disposed<br/>
95 /// </summary>
96 /// <typeparam name="T">Repository type</typeparam>
97 /// <returns></returns>
98 public T GetRepo<T>()
99 where T : BaseDataRepository, new()
100 {
101 return mInstance.GetRepo<T>();
102 }
103
104 /// <summary>
105 /// -> Gets or creates a new tracking T repository <br/>
106 /// -> Once created, the repo instance will "exist" until the [RepoContext] instance is Disposed<br/>
107 /// </summary>
108 /// <typeparam name="T">Repository type</typeparam>
109 /// <returns></returns>
110 public T GetTrackingRepo<T>()
111 where T : BaseDataRepository, new()
112 {
113 return mInstance.GetTrackingRepo<T>();
114 }
115
116 /// <summary>
117 /// This will do the commit logic only of Level is 0 (if this is the original context) or IsEnableChildren = true
118 /// </summary>
119 public void CommitTransaction()
120 {
121 if (Level == 0 || mEnableChildren)
122 {
123 mInstance.UnitOfWork.CommitTransaction();
124 }
125 }
126
127 public bool IsTransactionFinalized => mInstance.UnitOfWork.IsTransactionFinalized;
128
129 /// <summary>
130 /// This will do the rollback logic only if Level is 0 (if this is the original context) or IsEnableChildren = true
131 /// </summary>
132 public void RollbackTransaction()
133 {
134 if (Level == 0 || mEnableChildren)
135 {
136 mInstance.UnitOfWork.RollbackTransaction();
137 }
138 }
139
140 /// <summary>
141 /// -> Use this to pass a "safe" copy into a function <br/>
142 /// -> eg. MyMethodThatUsesAUnitOfWorkAndMayCreateNewRepos(context.NewChildContext() , ...)
143 /// </summary>
144 /// <returns></returns>
145 public RepoContext NewChildContext()
146 {
147 return new RepoContext(this);
148 }
149
150 public static RepoContext NewContext(bool enableChildren = false)
151 {
152 return new RepoContext(enableChildren);
153 }
154
155 #endregion
156
157 #region PRIVATE API
158
159 private RepoContext(bool enableChildren)
160 {
161 mEnableChildren = enableChildren;
162
163 mInstance = new RepoContextBase();
164 }
165
166 private RepoContext(RepoContext parent)
167 {
168 //New level
169 Level = parent.Level + 1;
170
171 //Same instance
172 mInstance = parent.mInstance;
173
174 //Same enable children
175 mEnableChildren = parent.mEnableChildren;
176 }
177
178 #endregion
179
180 #region IDISPOSABLE
181
182 public void Dispose()
183 {
184 if (mInstance != null)
185 {
186 mInstance.Dispose();
187 mInstance = null;
188 }
189 }
190
191 #endregion
192 }
193}