zoukankan      html  css  js  c++  java
  • CRUD全栈式编程架构之服务层的设计

    服务层代码

    首先我先放出2个主要类的代码再分别讲解

    接口

    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只是一个泛型限制里面暂时没有任何实现

    以下是一个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只是一个泛型限制,里面暂时没有任何实现

    泛型维度的缩放


    对于上面排序和查询的功能并不是一定都需要,所以做了维度缩放,可以从三种
    维度去使用Crud的服务.
    对于服务的实现上加入了模型实体(也就是和数据库映射的模型),这么做的好处是
    使用接口的人无需知道数据库怎么存放表怎么映射,接口和实现分离。

    Mapper

    我们选用EmitMapper作为Entity和DTO的映射,目前来看这个性能是除了直接赋值
    之外性能最好的了,网上有很多对比文章请自行参考。当然如果你不习惯也可以
    换一种实现

    这里代码参考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更新机制

    EF更新这也是我经常使用的一个面试题,很多人会回答直接由Update方法可以调用
    实际上ef是通过代理对象并且实现INotifyChange接口来监听属性的改变。
    EF更新的时候不能修改主键的值,所以我这里做了忽略。其他属性全部更新,
    当然如果涉及到具体业务比如修改账号或者金额之类的修改,最好是扩展服务实现
    不要用这个服务中自带的更新方法,直接使用Repository去更新

    Attribute注入配置化

    这里我使用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

    这里EventBus参考Abp和ApWorks的设计,这个发送的不算领域事件,是应用层
    事件,在我项目中Event主要使用在三个地方
    >*  统计模块预定事件以后可以根据设计好的查询需求去存放数据
        这样会比原来从原始表中load数据快很多.
    >*  在比如菜单中可以注册类型的事件实现菜单的动态修改。
        这个会在做界面层的时候提到
    >*  缓存数据的即时更新

  • 相关阅读:
    uiautomator2自动化测试
    APP性能测试(电池电量、流量、CPU、内存)
    python虚拟环境搭建
    unittest报错(return self._request(command_info[0], url, body=data))
    python pip错误处理
    adb 实用命令
    大数据学习(一)
    windows 下Virtualenv搭建mysql环境
    python奇怪毛病集合
    python作业
  • 原文地址:https://www.cnblogs.com/Skyven/p/5645419.html
Copyright © 2011-2022 走看看