首先我先放出2個主要類的代碼再分別講解面試
接口sql
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Coralcode.Framework.Models; using Coralcode.Framework.Page; namespace Coralcode.Framework.Services { /// <summary> /// 全功能增刪改查服務 /// </summary> /// <typeparam name="TModel"></typeparam> /// <typeparam name="TSearch"></typeparam> /// <typeparam name="TOrder"></typeparam> public interface ICrudCoralService<TModel, in TSearch, in TOrder> : IServiceWithContext where TModel : class, IViewModel, new() where TSearch : SearchBase where TOrder : OrderBase { TModel Get(long id); void Create(TModel model); void Create(List<TModel> models); void Modify(TModel model); void Modify(List<TModel> model); void Remove(long id); void Remove(List<long> ids); List<TModel> GetAll(); List<TModel> Search(TSearch search); PagedList<TModel> PageSearch(PageInfo page, TSearch search, TOrder order); } /// <summary> /// 默認排序的增刪改查服務 /// </summary> /// <typeparam name="TModel"></typeparam> /// <typeparam name="TSearch"></typeparam> public interface ICrudCoralService<TModel, in TSearch> : ICrudCoralService<TModel, TSearch, OrderBase> where TModel : class, IViewModel, new() where TSearch : SearchBase { } /// <summary> /// 默認查詢的增刪改查服務 /// </summary> /// <typeparam name="TModel"></typeparam> public interface ICrudCoralService<TModel> : ICrudCoralService<TModel, SearchBase, OrderBase> where TModel : class, IViewModel, new() { } }
實現數據庫
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; using Coralcode.Framework.Aspect.Unity; using Coralcode.Framework.Data.Repository; using Coralcode.Framework.Data.Repository.Core; using Coralcode.Framework.Data.Specification; using Coralcode.Framework.Domains; using Coralcode.Framework.Exceptions; using Coralcode.Framework.Mapper; using Coralcode.Framework.MessageBus.Event; using Coralcode.Framework.MessageBus.EventHandlers.Entities; using Coralcode.Framework.Models; using Coralcode.Framework.Page; using EmitMapper.MappingConfiguration; namespace Coralcode.Framework.Services { public abstract class CrudCoralService<TEntity, TModel, TSearch, TOrder> : CoralService, ICrudCoralService<TModel, TSearch, TOrder> where TEntity : Entity, new() where TModel : class, IViewModel, new() where TSearch : SearchBase where TOrder : OrderBase { protected IRepository<TEntity> Repository; /// <summary> /// 這裏爲了隱藏事件總線這一複雜東西 /// </summary> protected IEventBus EventBus; protected CrudCoralService(IRepository<TEntity> repository, IEventBus eventBus) { Repository = repository; EventBus = eventBus; } public virtual TModel Get(long id) { var entity = Repository.Get(id); if (entity == null) return null; return Convert(entity); } public virtual void Create(TModel model) { var entity = Convert(model); entity.Id = model.Id; Repository.Add(entity); model.Id = entity.Id; Repository.UnitOfWork.Commit(); EventBus.Publish(new EntityCreatedEventData<TModel>(model)); } public virtual void Create(List<TModel> models) { models.ForEach(model => { var entity = Convert(model); Repository.Add(entity); model.Id = entity.Id; }); Repository.UnitOfWork.Commit(); models.ForEach(model => { EventBus.Publish(new EntityCreatedEventData<TModel>(model)); }); } public virtual void Modify(TModel model) { var entity = Repository.Get(model.Id); if (entity == null) throw new NotFoundException("實體沒有找到"); var oldModel = Convert(entity); Convert(model, entity); Repository.Modify(entity); Repository.UnitOfWork.Commit(); EventBus.Publish(new EntityModifyEventData<TModel>(model, oldModel)); } public void Modify(List<TModel> models) { var items = new List<KeyValuePair<TModel, TModel>>(); models.ForEach(model => { var entity = Repository.Get(model.Id); if (entity == null) return; var oldModel = Convert(entity); items.Add(new KeyValuePair<TModel, TModel>(model, oldModel)); Convert(model, entity); Repository.Modify(entity); Repository.UnitOfWork.Commit(); }); Repository.UnitOfWork.Commit(); items.ForEach(item => { EventBus.Publish(new EntityModifyEventData<TModel>(item.Key, item.Value)); }); } public virtual void Remove(long id) { var item = Get(id); if (item == null) return; Repository.Remove(id); Repository.UnitOfWork.Commit(); EventBus.Publish(new EntityRemoveEventData<TModel>(item)); } public virtual void Remove(List<long> ids) { var items = new List<TModel>(); ids.ForEach(id => { items.Add(Get(id)); Repository.Remove(id); }); Repository.UnitOfWork.Commit(); items.ForEach(item => { EventBus.Publish(new EntityRemoveEventData<TModel>(item)); }); } public virtual List<TModel> GetAll() { return Repository.GetAll().Select(Convert).ToList(); } public virtual List<TModel> Search(TSearch search) { return Repository.GetAllMatching(GetFilter(search)).Select(Convert).ToList(); } public PagedList<TModel> PageSearch(PageInfo page, TSearch search, TOrder order) { return Repository.GetPaged(page.PageIndex, page.PageSize, GetFilter(search),new SortExpression<TEntity>(GetOrder(order))).ConvertToPagedList(Convert); } protected virtual ISpecification<TEntity> GetFilter(TSearch search) { return new DirectSpecification<TEntity>(item => item.Id > 0); } protected virtual List<EditableKeyValuePair<Expression<Func<TEntity, dynamic>>, bool>> GetOrder(TOrder order) { return new List<EditableKeyValuePair<Expression<Func<TEntity, dynamic>>, bool>> { new EditableKeyValuePair<Expression<Func<TEntity, dynamic>>, bool>(item=>item.Id,true), }; } /// <summary> /// 出來轉換 /// </summary> /// <param name="entity"></param> /// <returns></returns> protected virtual TModel Convert(TEntity entity) { return DataMapperProvider.Mapper.Convert<TEntity, TModel>(entity); } /// <summary> /// 進入轉換 /// </summary> /// <param name="model"></param> /// <returns></returns> protected virtual TEntity Convert(TModel model) { return DataMapperProvider.Mapper.Convert<TModel, TEntity>(model, new DefaultMapConfig().IgnoreMembers<TModel, TEntity>(new[] { "Id" })); } /// <summary> /// 屬性賦值 /// </summary> /// <param name="model"></param> /// <param name="entity"></param> protected virtual void Convert(TModel model, TEntity entity) { DataMapperProvider.Mapper.Convert(model, entity, new DefaultMapConfig().IgnoreMembers<TModel, TEntity>(new[] { "Id" })); } } public abstract class CrudCoralService<TEntity, TModel, TSearch> : CrudCoralService<TEntity, TModel, TSearch, OrderBase> where TEntity : Entity, new() where TModel : class, IViewModel, new() where TSearch : SearchBase { protected CrudCoralService(IRepository<TEntity> repository, IEventBus eventBus) : base(repository, eventBus) { } } public abstract class CrudCoralService<TEntity, TModel> : CrudCoralService<TEntity, TModel, SearchBase, OrderBase> where TEntity : Entity, new() where TModel : class, IViewModel, new() { protected CrudCoralService(IRepository<TEntity> repository, IEventBus eventBus) : base(repository, eventBus) { } } }
上一節提到Specification實現查詢功能,主要實現Where功能, 可是查詢還須要數據承載,查詢實體就是數據的承載,其中數據到 表達式或者sql的拼接就是在GetFilter中實現的,這裏要注意寫法特別是 expression=expression.And(xxx).必定要賦值給本身。SearchBase只是一個泛型限制裏面暫時沒有任何實現express
如下是一個GetFilter實現緩存
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只是一個泛型限制,裏面暫時沒有任何實現app
對於上面排序和查詢的功能並非必定都須要,因此作了維度縮放,能夠從三種
維度去使用Crud的服務.
對於服務的實現上加入了模型實體(也就是和數據庫映射的模型),這麼作的好處是
使用接口的人無需知道數據庫怎麼存放表怎麼映射,接口和實現分離。框架
咱們選用EmitMapper做爲Entity和DTO的映射,目前來看這個性能是除了直接賦值
以外性能最好的了,網上有不少對比文章請自行參考。固然若是你不習慣也能夠
換一種實現ide
這裏代碼參考NLayerApp中Mapper的設計,略做修改函數
注意這裏配置文件採用Dynamic的方式可讓簡單使用的地方不須要引用EmitMapper,性能
除非是要作一些擴展
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更新這也是我常用的一個面試題,不少人會回答直接由Update方法能夠調用
實際上ef是經過代理對象而且實現INotifyChange接口來監聽屬性的改變。
EF更新的時候不能修改主鍵的值,因此我這裏作了忽略。其餘屬性所有更新,
固然若是涉及到具體業務好比修改帳號或者金額之類的修改,最好是擴展服務實現
不要用這個服務中自帶的更新方法,直接使用Repository去更新
這裏我使用Attribute作Ioc配置,其中生命週期的枚舉參考unity框架的設計,
具體怎麼使用能夠參考網上的文章。
實現機制是在一個用啓動的時候掃描程序集有這個標記的類型,而後讀出
RegisterType作註冊,而且支持多註冊
UnityService的代碼
注意這裏Register方法最後一個參數用dynamic,這樣使用的地方就能夠不依賴於Unity,
其中包含了Aop和幾個設計技巧,有問題的能夠留言我再作解答
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); } } }
輔助類
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, }
}
Aop輔助類
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參考Abp和ApWorks的設計,這個發送的不算領域事件,是應用層事件,在我項目中Event主要使用在三個地方>* 統計模塊預約事件之後能夠根據設計好的查詢需求去存放數據 這樣會比原來從原始表中load數據快不少.>* 在好比菜單中能夠註冊類型的事件實現菜單的動態修改。 這個會在作界面層的時候提到>* 緩存數據的即時更新