服务层的设计
服务层代码
首先我先放出2个主要类的代码再分别讲解
接口
实现
查询实体
上一节提到Specification实现查询功能,主要实现Where功能, 但是查询还需要数据承载,查询实体就是数据的承载,其中数据到 表达式或者sql的拼接就是在GetFilter中实现的,这里要注意写法特别是 expression=expression.And(xxx).一定要赋值给自己。SearchBase只是一个泛型限制里面暂时没有任何实现
以下是一个GetFilter实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
protected override ISpecification<PrivateLesson> GetFilter(LessonSearch search) { var expression = (Expression<Func<PrivateLesson, bool >>)(item => true ); if (search == null ) return base .GetFilter( null ); if (search.StartTime != default (DateTime)) expression = expression.And(item => item.StartTime > search.StartTime); if (search.EndTime != default (DateTime)) expression = expression.And(item => item.StartTime < search.EndTime); if (! string .IsNullOrWhiteSpace(search.Text)) expression = expression.And(item => item.Name.Contains(search.Text) || item.Coach.Name.Contains(search.Text)); return new DirectSpecification<PrivateLesson>(expression); } |
排序实体
等同于查询实体,排序实体也是排序功能的数据承载,OrderBase只是一个泛型限制,里面暂时没有任何实现
泛型维度的缩放
对于上面排序和查询的功能并不是一定都需要,所以做了维度缩放,可以从三种
维度去使用Crud的服务.
对于服务的实现上加入了模型实体(也就是和数据库映射的模型),这么做的好处是
使用接口的人无需知道数据库怎么存放表怎么映射,接口和实现分离。
Mapper
我们选用EmitMapper作为Entity和DTO的映射,目前来看这个性能是除了直接赋值
之外性能最好的了,网上有很多对比文章请自行参考。当然如果你不习惯也可以
换一种实现
这里代码参考NLayerApp中Mapper的设计,略作修改
注意这里配置文件采用Dynamic的方式可以让简单使用的地方不需要引用EmitMapper,
除非是要做一些扩展
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
namespace Coralcode.Framework.Mapper { public class DataMapperProvider { public static IDataMapper Mapper { get { return new EmitmapperDataMapper(); } } } } namespace Coralcode.Framework.Mapper { public interface IDataMapper { TTarget Convert<TSource, TTarget>(TSource source) where TTarget : class , new () where TSource : class ; TTarget Convert<TSource, TTarget>(TSource source, TTarget target) where TTarget : class where TSource : class ; /// <summary> /// 带配置文件的转换 /// </summary> /// <typeparam name="TSource"></typeparam> /// <typeparam name="TTarget"></typeparam> /// <param name="source"></param> /// <param name="target"></param> /// <param name="config">配置文件</param> /// <returns></returns> TTarget Convert<TSource, TTarget>(TSource source, TTarget target, dynamic config) where TTarget : class where TSource : class ; /// <summary> /// 带配置文件的转换 /// </summary> /// <typeparam name="TSource"></typeparam> /// <typeparam name="TTarget"></typeparam> /// <param name="source"></param> /// <param name="config">配置文件</param> /// <returns></returns> TTarget Convert<TSource, TTarget>(TSource source, dynamic config) where TTarget : class , new () where TSource : class ; } } using EmitMapper; using EmitMapper.MappingConfiguration; namespace Coralcode.Framework.Mapper { public class EmitmapperDataMapper : IDataMapper { #region ITypeAdapter Members public TTarget Convert<TSource, TTarget>(TSource source) where TSource : class where TTarget : class , new () { ObjectsMapper<TSource, TTarget> mapper = ObjectMapperManager.DefaultInstance.GetMapper<TSource, TTarget>( new DefaultMapConfig()); return mapper.Map(source); } public TTarget Convert<TSource, TTarget>(TSource source, TTarget target) where TTarget : class where TSource : class { ObjectsMapper<TSource, TTarget> mapper = ObjectMapperManager.DefaultInstance.GetMapper<TSource, TTarget>( new DefaultMapConfig()); return mapper.Map(source, target); } public TTarget Convert<TSource, TTarget>(TSource source, TTarget target, dynamic config) where TTarget : class where TSource : class { ObjectsMapper<TSource, TTarget> mapper = ObjectMapperManager.DefaultInstance.GetMapper<TSource, TTarget>((DefaultMapConfig)config); return mapper.Map(source, target); } public TTarget Convert<TSource, TTarget>(TSource source, dynamic config) where TTarget : class , new () where TSource : class { ObjectsMapper<TSource, TTarget> mapper = ObjectMapperManager.DefaultInstance.GetMapper<TSource, TTarget>(config); return mapper.Map(source); } #endregion } } |
EF更新机制
EF更新这也是我经常使用的一个面试题,很多人会回答直接由Update方法可以调用
实际上ef是通过代理对象并且实现INotifyChange接口来监听属性的改变。
EF更新的时候不能修改主键的值,所以我这里做了忽略。其他属性全部更新,
当然如果涉及到具体业务比如修改账号或者金额之类的修改,最好是扩展服务实现
不要用这个服务中自带的更新方法,直接使用Repository去更新
Attribute注入配置化
这里我使用Attribute做Ioc配置,其中生命周期的枚举参考unity框架的设计,
具体怎么使用可以参考网上的文章。
实现机制是在一个用启动的时候扫描程序集有这个标记的类型,然后读出
RegisterType做注册,并且支持多注册
UnityService的代码
注意这里Register方法最后一个参数用dynamic,这样使用的地方就可以不依赖于Unity,
其中包含了Aop和几个设计技巧,有问题的可以留言我再做解答
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
|
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using Coralcode.Framework.Extensions; using Coralcode.Framework.Reflection; using Microsoft.Practices.Unity; using Microsoft.Practices.Unity.InterceptionExtension; namespace Coralcode.Framework.Aspect.Unity { /// <summary> /// IOC容器 /// </summary> public class UnityService { static UnityService() { //注册标记 Current = new UnityContainer(); Current.AddNewExtension<Interception>(); var currentType = typeof (UnityService); var containers = new List<dynamic>(); //模块初始化 containers.ForEach(item => item.Regist()); //模块启动 containers.ForEach(item => item.RegistComplete()); MetaDataManager.Type.GetAllTypes().ForEach(item => { if (item == null ) return ; var registers = item.GetCustomAttributes<InjectAttribute>().ToList(); if (registers.Count == 0) return ; registers.ForEach(register => { if (register.RegisterType != null ) RegisterType(register.Name, register.RegisterType, item, GetLifetimeManager(register.LifetimeManagerType), GetInjectionMembers(register.AopType, item)); else RegisterType(register.Name, item, GetLifetimeManager(register.LifetimeManagerType), GetInjectionMembers(register.AopType, item)); }); }); } #region 属性 /// <summary> /// Get the current configured container /// </summary> /// <returns>Configured container</returns> private static IUnityContainer Current { get ; set ; } #endregion /// <summary> /// 在当前模块中注册接口的实现 /// </summary> protected virtual void Regist() { } /// <summary> /// 在当前模块中注册应用程序启动事件 /// </summary> protected virtual void RegistComplete() { } #region 注册相关的方法 /// <summary> /// 获取生命周期 /// </summary> /// <param name="lifetimeManagerType"></param> /// <returns></returns> public static LifetimeManager GetLifetimeManager(LifetimeManagerType lifetimeManagerType) { switch (lifetimeManagerType) { case LifetimeManagerType.Transient: return new TransientLifetimeManager(); case LifetimeManagerType.ContainerControlled: return new ContainerControlledLifetimeManager(); case LifetimeManagerType.Hierarchica: return new HierarchicalLifetimeManager(); case LifetimeManagerType.Externally: return new ExternallyControlledLifetimeManager(); case LifetimeManagerType.PerThread: return new PerThreadLifetimeManager(); case LifetimeManagerType.PerResolve: return new PerResolveLifetimeManager(); default : return new TransientLifetimeManager(); } } /// <summary> /// 注入aop方法 /// </summary> /// <param name="aopType"></param> /// <param name="type"></param> /// <returns></returns> public static InjectionMember[] GetInjectionMembers(AopType aopType, Type type) { var members = new List<InjectionMember>(); switch (aopType) { case AopType.VirtualMethodInterceptor: members.Add( new Interceptor<VirtualMethodInterceptor>()); break ; case AopType.InterfaceInterceptor: members.Add( new Interceptor<InterfaceInterceptor>()); break ; case AopType.TransparentProxyInterceptor: members.Add( new Interceptor<TransparentProxyInterceptor>()); break ; } members.AddRange(type.GetCustomAttributes() .Where(item => item.GetType().IsSubclassOf( typeof (UnityAopAttribute))) .Cast<UnityAopAttribute>() .Select(item => new InterceptionBehavior(item))); return members.ToArray(); } #endregion /// <summary> /// 注册泛型类型 /// </summary> /// <param name="injectionMembers">构造函数参数</param> public static void Register<TTarget, TSource>( params dynamic[] injectionMembers) where TSource : TTarget { RegisterType<TTarget, TSource>( "" ,injectionMembers); } /// <summary> /// 注册泛型类型 /// </summary> /// <param name="name"></param> /// <param name="injectionMembers">构造函数参数</param> public static void RegisterType<TTarget, TSource>( string name, params dynamic[] injectionMembers) where TSource : TTarget { var members = new List<InjectionMember>(); LinqExtensions.ForEach(injectionMembers, item => { if (item is InjectionMember) members.Add(item); if (item is InjectionMember[]) members.AddRange(item); else if (item is ConstructorParameter) members.Add( new InjectionConstructor(item.Value)); else if (item is ConstructorParameter[]) members.AddRange((item as ConstructorParameter[]).Select(data => new InjectionConstructor(data.Value))); }); var lifetimeManager = injectionMembers.OfType<LifetimeManager>().FirstOrDefault(); if ( string .IsNullOrEmpty(name)) { if (lifetimeManager == null && injectionMembers == null ) Current.RegisterType<TTarget, TSource>(); else if (lifetimeManager == null ) Current.RegisterType<TTarget, TSource>(members.ToArray()); else if (injectionMembers == null ) Current.RegisterType<TTarget, TSource>(lifetimeManager); else Current.RegisterType<TTarget, TSource>(lifetimeManager, members.ToArray()); } else { if (lifetimeManager == null && injectionMembers == null ) Current.RegisterType<TTarget, TSource>(name); else if (lifetimeManager == null ) Current.RegisterType<TTarget, TSource>(name, members.ToArray()); else if (injectionMembers == null ) Current.RegisterType<TTarget, TSource>(name, lifetimeManager); else Current.RegisterType<TTarget, TSource>(name, lifetimeManager, members.ToArray()); } } /// <summary> /// 注册类型 /// </summary> /// <param name="source"></param> /// <param name="target"></param> /// <param name="lifetimeManager"></param> /// <param name="injectionMembers"></param> public static void RegisterType( string name, Type target, Type source, params dynamic[] injectionMembers) { var members = new List<InjectionMember>(); LinqExtensions.ForEach(injectionMembers, item => { if (item is InjectionMember) members.Add(item); if (item is InjectionMember[]) members.AddRange(item); else if (item is ConstructorParameter) members.Add( new InjectionConstructor(item.Value)); else if (item is ConstructorParameter[]) members.AddRange((item as ConstructorParameter[]).Select(data => new InjectionConstructor(data.Value))); }); var lifetimeManager = injectionMembers.OfType<LifetimeManager>().FirstOrDefault(); if ( string .IsNullOrEmpty(name)) { if (lifetimeManager == null && injectionMembers == null ) Current.RegisterType(target, source); else if (lifetimeManager == null ) Current.RegisterType(target, source, members.ToArray()); else if (injectionMembers == null ) Current.RegisterType(target, source, lifetimeManager); else Current.RegisterType(target, source, lifetimeManager, members.ToArray()); } else { if (lifetimeManager == null && injectionMembers == null ) Current.RegisterType(target, source, name); else if (lifetimeManager == null ) Current.RegisterType(target, source, name, members.ToArray()); else if (injectionMembers == null ) Current.RegisterType(target, source, name, lifetimeManager); else Current.RegisterType(target, source, name, lifetimeManager, members.ToArray()); } } /// <summary> /// 注册类型 /// </summary> /// <param name="source"></param> /// <param name="target"></param> /// <param name="lifetimeManager"></param> /// <param name="injectionMembers"></param> public static void RegisterType(Type target, Type source, params dynamic[] injectionMembers) { var members = new List<InjectionMember>(); LinqExtensions.ForEach(injectionMembers, item => { if (item is InjectionMember) members.Add(item); if (item is InjectionMember[]) members.AddRange(item); else if (item is ConstructorParameter) members.Add( new InjectionConstructor(item.Value)); else if (item is ConstructorParameter[]) members.AddRange((item as ConstructorParameter[]).Select(data => new InjectionConstructor(data.Value))); }); var lifetimeManager = injectionMembers.OfType<LifetimeManager>().FirstOrDefault(); if (lifetimeManager == null && injectionMembers == null ) Current.RegisterType(target, source); else if (lifetimeManager == null ) Current.RegisterType(target, source, members.ToArray()); else if (injectionMembers == null ) Current.RegisterType(target, source, lifetimeManager); else Current.RegisterType(target, source, lifetimeManager, members.ToArray()); } /// <summary> /// 注册类型 /// </summary> /// <param name="injectionMembers"></param> public static void RegisterType(Type type, params dynamic[] injectionMembers) { var members = new List<InjectionMember>(); LinqExtensions.ForEach(injectionMembers, item => { if (item is InjectionMember) members.Add(item); if (item is InjectionMember[]) members.AddRange(item); else if (item is ConstructorParameter) members.Add( new InjectionConstructor(item.Value)); else if (item is ConstructorParameter[]) members.AddRange((item as ConstructorParameter[]).Select(data => new InjectionConstructor(data.Value))); }); var lifetimeManager = injectionMembers.OfType<LifetimeManager>().FirstOrDefault(); if (lifetimeManager == null && injectionMembers == null ) Current.RegisterType(type); else if (lifetimeManager == null ) Current.RegisterType(type, members.ToArray()); else if (injectionMembers == null ) Current.RegisterType(type, lifetimeManager); else Current.RegisterType(type, lifetimeManager, members.ToArray()); } /// <summary> /// 注册类型 /// </summary> /// <param name="type"></param> /// <param name="injectionMembers"></param> /// <param name="name"></param> public static void RegisterType( string name, Type type, params dynamic[] injectionMembers) { var members = new List<InjectionMember>(); LinqExtensions.ForEach(injectionMembers, item => { if (item is InjectionMember) members.Add(item); if (item is InjectionMember[]) members.AddRange(item); else if (item is ConstructorParameter) members.Add( new InjectionConstructor(item.Value)); else if (item is ConstructorParameter[]) members.AddRange((item as ConstructorParameter[]).Select(data => new InjectionConstructor(data.Value))); }); var lifetimeManager = injectionMembers.OfType<LifetimeManager>().FirstOrDefault(); if ( string .IsNullOrEmpty(name)) { if (lifetimeManager == null && injectionMembers == null ) Current.RegisterType(type); else if (lifetimeManager == null ) Current.RegisterType(type, members.ToArray()); else if (injectionMembers == null ) Current.RegisterType(type, lifetimeManager); else Current.RegisterType(type, lifetimeManager, members.ToArray()); } else { if (lifetimeManager == null && injectionMembers == null ) Current.RegisterType(type, name); else if (lifetimeManager == null ) Current.RegisterType(type, name, members.ToArray()); else if (injectionMembers == null ) Current.RegisterType(type, name, lifetimeManager); else Current.RegisterType(type, name, lifetimeManager, members.ToArray()); } } /// <summary> /// 创建实例 /// </summary> /// <param name="source"></param> /// <returns></returns> public static object Resolve(Type source) { return Current.Resolve(source); } private static ConcurrentDictionary< string , Action<dynamic>> _handles = new ConcurrentDictionary< string , Action<dynamic>>(); /// <summary> /// 当创建新实例时触发 /// </summary> /// <param name="handler"></param> /// <returns></returns> public void OnCreation<T>(Action<T> handler) { _handles.TryAdd( typeof (T).FullName, item => handler(item.Data)); } public static bool HasRegistered(Type type) { return Current.IsRegistered(type); } /// <summary> /// 创建泛型实例 /// </summary> /// <returns></returns> public static T Resolve<T>() { var result = Current.Resolve<T>(); Action<dynamic> handler; if (_handles.TryGetValue( typeof (T).FullName, out handler)) { handler( new EventArgs<T>(result)); } return result; } /// <summary> /// 创建泛型实例 /// </summary> /// <returns></returns> public static T Resolve<T>( string name) { return Current.Resolve<T>(name); } /// <summary> /// 创建泛型实例集合 /// </summary> /// <returns></returns> public static T[] ResolveAll<T>() { var serviceImpls = Current.ResolveAll<T>(); List<T> proxiedServiceImpls = new List<T>(); foreach ( var serviceImpl in serviceImpls) { Action<dynamic> handler; if (_handles.TryGetValue( typeof (T).FullName, out handler)) { handler( new EventArgs<T>(serviceImpl)); } proxiedServiceImpls.Add(serviceImpl); } return proxiedServiceImpls.ToArray(); } public static void Release( object obj) { Current.Teardown(obj); } } } |
辅助类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
using System; namespace Coralcode.Framework.Aspect { [AttributeUsage(AttributeTargets.Class, AllowMultiple = true )] public class InjectAttribute : Attribute { /// <summary> /// 注册的名字 /// </summary> public string Name { get ; set ; } /// <summary> /// 依赖注入的类型 /// </summary> public Type RegisterType { get ; set ; } /// <summary> /// 注册条件 /// </summary> public RegisterCondition Condition { get ; set ; } /// <summary> /// aop类型 /// </summary> public AopType AopType { get ; set ; } /// <summary> /// 生命周期类型 /// </summary> public LifetimeManagerType LifetimeManagerType { get ; set ; } } [Flags] public enum RegisterCondition { /// <summary> /// 是否必须 /// </summary> IsRequire = 1, } /// <summary> /// 拦截类型 /// </summary> public enum AopType { /// <summary> /// 不拦截 /// </summary> None, /// <summary> /// 虚方法拦截 /// </summary> VirtualMethodInterceptor, /// <summary> /// 接口拦截 /// </summary> InterfaceInterceptor, /// <summary> /// 动态代理拦截 /// </summary> TransparentProxyInterceptor, //这里可以添加自定义 } public enum LifetimeManagerType { /// <summary> /// 每次通过Resolve或ResolveAll调用对象的时候都会重新创建一个新的对象。 /// </summary> Transient, /// <summary> /// 容器控制生命周期管理,这个生命周期管理器是RegisterInstance默认使用的生命周期管理器,也就是单件实例 /// </summary> ContainerControlled, /// <summary> /// 分层生命周期管理器,这个管理器类似于ContainerControlledLifetimeManager, /// 也是由UnityContainer来管理,也就是单件实例。 /// 不过与ContainerControlledLifetimeManager不 同的是, /// 这个生命周期管理器是分层的, /// 因为Unity的容器时可以嵌套的,所以这个生命周期管理器就是针对这种情况, /// 当使用了这种生命周期管理器, /// 父容器 和子容器所维护的对象的生命周期是由各自的容器来管理 /// </summary> Hierarchica, /// <summary> /// 外部控制生命周期管理器,这个 生命周期管理允许你使用RegisterType和RegisterInstance来注册对象之间的关系, /// 但是其只会对对象保留一个弱引用, /// 其生命周期 交由外部控制,也就是意味着你可以将这个对象缓存或者销毁而不用在意UnityContainer, /// 而当其他地方没有强引用这个对象时,其会被GC给销毁 掉。 /// </summary> Externally, /// <summary> /// 每线程生命周期管理器,就是保证每个线程返回同一实例 /// </summary> PerThread, /// <summary> /// 其类似于 TransientLifetimeManager,但是其不同在于, /// 如果应用了这种生命周期管理器, /// 则在第一调用的时候会创建一个新的对象, /// 而再次通过 循环引用访问到的时候就会返回先前创建的对象实例(单件实例), /// </summary> PerResolve, }<br>} |
Aop辅助类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
using System; using Microsoft.Practices.Unity; using Microsoft.Practices.Unity.InterceptionExtension; namespace Coralcode.Framework.Aspect.Unity { [AttributeUsage(AttributeTargets.Method|AttributeTargets.Class|AttributeTargets.Interface)] public abstract class UnityAopAttribute : HandlerAttribute, ICallHandler, IInterceptionBehavior { public override ICallHandler CreateHandler(IUnityContainer container) { return this ; } public System.Collections.Generic.IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; } /// <summary> /// 调用之后的实现逻辑 /// </summary> /// <param name="input"></param> /// <returns></returns> protected virtual void OnAfter(IMethodInvocation input) { } /// <summary> /// 调用之前的实现逻辑 /// </summary> /// <param name="input"></param> /// <returns></returns> protected virtual void OnBefore(IMethodInvocation input) { } /// <summary> /// 调用出现异常的实现逻辑 /// </summary> /// <param name="input"></param> /// <returns></returns> protected virtual void OnException(IMethodInvocation input, Exception ex) { throw ex; } /// <summary> /// 接口注入时候的拦截方法 /// </summary> /// <param name="input"></param> /// <param name="nextMethod"></param> /// <returns></returns> public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate nextMethod) { OnBefore(input); IMethodReturn result = null ; try { result = nextMethod()(input, nextMethod); } catch (Exception ex) { OnException(input, ex); } OnAfter(input); return result; } /// <summary> /// 虚方法注入的拦截方法 /// </summary> /// <param name="input"></param> /// <param name="nextMethod"></param> /// <returns></returns> public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate nextMethod) { OnBefore(input); IMethodReturn result= null ; try { result = nextMethod()(input, nextMethod); } catch (Exception ex) { OnException(input, ex); } OnAfter(input); return result; } public bool WillExecute { get { return true ; } } } } |
得益于Mvc的filter,实际项目中很少用到AOP,如果需要使用继承自这个类并标记在需要拦截的地方即可
EventBus
这里EventBus参考Abp和ApWorks的设计,这个发送的不算领域事件,是应用层
事件,在我项目中Event主要使用在三个地方
>* 统计模块预定事件以后可以根据设计好的查询需求去存放数据
这样会比原来从原始表中load数据快很多.
>* 在比如菜单中可以注册类型的事件实现菜单的动态修改。
这个会在做界面层的时候提到
>* 缓存数据的即时更新