码迷,mamicode.com
首页 > 其他好文 > 详细

CRUD全栈式编程架构之服务层的设计

时间:2016-07-06 00:12:56      阅读:559      评论:0      收藏:0      [点我收藏+]

标签:

服务层代码

首先我先放出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)
        {            
       if (search == null) return base.GetFilter(null);
            var expression = (Expression<Func<PrivateLesson, bool>>)(item => true); 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数据快很多.
>*  在比如菜单中可以注册类型的事件实现菜单的动态修改。
    这个会在做界面层的时候提到
>*  缓存数据的即使更新

 

CRUD全栈式编程架构之服务层的设计

标签:

原文地址:http://www.cnblogs.com/Skyven/p/5645419.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!