最近公司新项目,须要搭架构进行开发,其中须要保证事务的一致性,通过一番查找,发现不少博文都是经过Spring.Net、Unity、PostSharp、Castle Windsor这些方式实现AOP的。可是这不是我想要的,所以一番查找后,使用Autofac、DynamicProxy
该方式实现AOP。c#
博主以为它的优点主要表如今:架构
定义属性,经过当前方法是否包含该属性进行判断开启事务,若是存在该属性则开启事务,不然忽略事务。
事务属性能够设置超时时间、事务范围以及事务隔离级别。
代码以下:ide
/// <summary> /// 开启事务属性 /// </summary> [AttributeUsage(AttributeTargets.Method,Inherited = true)] public class TransactionCallHandlerAttribute:Attribute { /// <summary> /// 超时时间 /// </summary> public int Timeout { get; set; } /// <summary> /// 事务范围 /// </summary> public TransactionScopeOption ScopeOption { get; set; } /// <summary> /// 事务隔离级别 /// </summary> public IsolationLevel IsolationLevel { get; set; } public TransactionCallHandlerAttribute() { Timeout = 60; ScopeOption=TransactionScopeOption.Required; IsolationLevel=IsolationLevel.ReadCommitted; } }
获取当前方法是否包含TransactionCallHandlerAttribute
该属性,若是有该属性则开启事务。
本人在此处加入开发模式判断,用于没设置MSDTC产生异常的问题,若是不须要可忽略。
另外日志功能自行实现便可。
代码以下:模块化
/// <summary> /// 事务 拦截器 /// </summary> public class TransactionInterceptor:IInterceptor { //可自行实现日志器,此处可忽略 /// <summary> /// 日志记录器 /// </summary> private static readonly ILog Logger = Log.GetLog(typeof(TransactionInterceptor)); // 是否开发模式 private bool isDev = false; public void Intercept(IInvocation invocation) { if (!isDev) { MethodInfo methodInfo = invocation.MethodInvocationTarget; if (methodInfo == null) { methodInfo = invocation.Method; } TransactionCallHandlerAttribute transaction = methodInfo.GetCustomAttributes<TransactionCallHandlerAttribute>(true).FirstOrDefault(); if (transaction != null) { TransactionOptions transactionOptions = new TransactionOptions(); //设置事务隔离级别 transactionOptions.IsolationLevel = transaction.IsolationLevel; //设置事务超时时间为60秒 transactionOptions.Timeout = new TimeSpan(0, 0, transaction.Timeout); using (TransactionScope scope = new TransactionScope(transaction.ScopeOption, transactionOptions)) { try { //实现事务性工做 invocation.Proceed(); scope.Complete(); } catch (Exception ex) { // 记录异常 throw ex; } } } else { // 没有事务时直接执行方法 invocation.Proceed(); } } else { // 开发模式直接跳过拦截 invocation.Proceed(); } } }
博主对Autofac
进行了封装,可能与大家的配置不同,可是,Load(ContainerBuilder builder)
该方法内容是一致的,所以注入方式一致的。
经过定义IDependency
空接口方式,须要注入的类则继承该接口便可。
代码以下:测试
/// <summary> /// 应用程序IOC配置 /// </summary> public class IocConfig : ConfigBase { // 重写加载配置 protected override void Load(ContainerBuilder builder) { var assembly = this.GetType().GetTypeInfo().Assembly; builder.RegisterType<TransactionInterceptor>(); builder.RegisterAssemblyTypes(assembly) .Where(type => typeof(IDependency).IsAssignableFrom(type) && !type.GetTypeInfo().IsAbstract) .AsImplementedInterfaces() .InstancePerLifetimeScope() .EnableInterfaceInterceptors() .InterceptedBy(typeof(TransactionInterceptor)); } }
/// <summary> /// 添加文章 /// </summary> /// <param name="name"></param> [TransactionCallHandler] public void AddArticle(string name) { BasArticle model=new BasArticle(); model.ArticleID = Guid.Empty;//故意重复,判断是否会回滚。 model.Code = TimestampId.GetInstance().GetId(); model.Name = name; model.Status = 1; model.Creater = "测试"; model.Editor = "测试"; this._basArticleRepository.Insert(model); }