服务层代码

首先我先放出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数据快很多.
>*  在比如菜单中可以注册类型的事件实现菜单的动态修改。
    这个会在做界面层的时候提到
>*  缓存数据的即时更新

CRUD全栈式编程架构之服务层的设计的更多相关文章

  1. CRUD全栈式编程架构之界面层的设计

    Layout的设计 模板模式 mvc的模板特别类似设计模式中模板方法模式,结合Layout中RenderSection和RenderBody方法可以将部分html展现逻辑延迟到具体的视图页面去实现里面 ...

  2. CRUD全栈式编程架构之控制器的设计

    页面 这里界面我采用jquery miniui来做的,当你完全了解了整个设计之后可以轻松切换到其他的js框架,个人认为类似muniui,easyui等等这类可以将web界面做得和winform类似的框 ...

  3. CRUD全栈式编程架构之导入导出的设计

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...

  4. CRUD全栈式编程架构之更精简的设计

    精简的程度 ViewModel精简 服务精简 控制器精简 Index.cshmtl精简 AddOrEdit.cshtml精简 效果:最精简的情况下,只需要写Entity这一个数据库实体然后加上一些简单 ...

  5. CRUD全栈式编程架构之数据层的设计

    CodeFirst 一直以来我们写应用的时候首先都是创建数据库 终于在orm支持codefirst之后,我们可以先建模. 通过模型去创建数据库,并且基于codefirst可以实现方便的 实现数据库迁移 ...

  6. CRUD全栈式编程架构之MVC的扩展设计

    MVC执行流程 路由的扩展 我理解的路由作用有以下几个 Seo优化,用“/”分开的url爬虫更爱吃 物理和逻辑文件分离,url不再按照文件路径映射 Controller,Action的选择 MVC路由 ...

  7. CRUD全栈式编程架构总结

    这里放出实例代码 github.com/SkyvenXiong/HCC

  8. CRUD全栈式编程概述

    业务场景 CRUD,从数据驱动的角度几乎所有的的业务都是在做这样的事情.  几乎所有的操作都是在做对表的增删改查.  假设我们将数据库数据规个类:  分为基础/配置数据和业务/增长数据,或者说静态数据 ...

  9. 全栈式JavaScript

    如今,在创建一个Web应用的过程中,你需要做出许多架构方面的决策.当然,你会希望做的每一个决定都是正确的:你想要使用能够快速开发的技术,支持持续的迭代,最高的工作效率,迅速,健壮性强.你想要精益求精并 ...

随机推荐

  1. Linux设备驱动开发基础--阻塞型设备驱动

    1. 当一个设备无法立刻满足用户的读写请求时(例如调用read时,设备没有数据提供),驱动程序应当(缺省的)阻塞进程,使它进入等待(睡眠)状态,知道请求可以得到满足. 2. Linux内核等待队列:在 ...

  2. Mercurial stuck “waiting for lock”, tortoisehg pull版本卡住在等待 解决办法

    最近使用hg的时候,拖取版本一直卡住不动.报错类似waiting for lock on working directory of xxxx held by ''. 原本以为是网络不好或者hg安装有问 ...

  3. vm12下Centos6的javaweb环境搭建

    配置linux的javaweb环境之前: 1.在windows安装xshell(非必需,但是推荐) 2.在linux安装Linux与windows文件传输工具RZSZ[root@192 ~]# yum ...

  4. 深入应用C++11:代码优化与工程级应用》勘误表

    https://www.cnblogs.com/qicosmos/p/4562174.html

  5. 轻量级ORM框架:Dapper中的一些复杂操作和inner join应该注意的坑

    上一篇博文中我们快速的介绍了dapper的一些基本CURD操作,也是我们manipulate db不可或缺的最小单元,这一篇我们介绍下相对复杂 一点的操作,源码分析暂时就不在这里介绍了. 一:tabl ...

  6. 日志logback

    http://tengj.top/2017/04/05/springboot7/ ------------------ logback使用指南. 公司配置 <?xml version=" ...

  7. TOJ 2815 Connect them (kruskal+并查集)

    描述 You have n computers numbered from 1 to n and you want to connect them to make a small local area ...

  8. Unity3D 发布成PC端常用设置

    本文,基于Unity 5.6pro版本来发布PC端.文中若有不妥之处,欢迎各位指出! 一.如何去掉Unity官方水印? 首先,你需要pro版本的Unity3D.如果,你是personal版本的话,就需 ...

  9. nagios监控远程端口

    check_port 位置:/usr/local/nagios/libexec/ 代码(新建可执行文件) #!/bin/sh /usr/local/nagios/libexec/check_tcp - ...

  10. Whu 1604——Play Apple——————【博弈】

    Problem 1604 - Play Apple Time Limit: 1000MS   Memory Limit: 65536KB   Total Submit: 442  Accepted: ...