zoukankan      html  css  js  c++  java
  • C#使用Castle实现AOP面向切面编程

    Castle.Core 本质是创建继承原来类的代理类,重写虚方法实现AOP功能。个人觉得比Autofac用着爽

    使用方式比较简单,先新建一个控制台项目,然后在Nuget上搜索Castle.Core并安装,如下顺序:

    或者通过命令安装:

    Install-Package Castle.Core -Version 3.3.3

    安装成功之后,如下图:

    1. 创建拦截器

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    //先在Nuget上搜索Castle安装
    using Castle.DynamicProxy;
    
    namespace CastleDEMO
    {
        /// <summary>
        /// 拦截器 需要实现 IInterceptor接口 Intercept方法
        /// </summary>
        public class DA_LogInterceptor : IInterceptor
        {
            public void Intercept(IInvocation invocation)
            {
                try
                {
                    DateTime begin = DateTime.Now;
    
                    Console.WriteLine("开始DAL {0}调用!", invocation.Method.Name);
    
                    //在被拦截的方法执行完毕后 继续执行
                    invocation.Proceed();
                    
                    DateTime end = DateTime.Now;
                    Console.WriteLine("结束DAL {0}调用!耗时:{1}ms", invocation.Method.Name, (end - begin).TotalMilliseconds);
                }
                catch (Exception ex)
                {
                    string methodName = "DA_" + invocation.TargetType.ToString() + "." + invocation.Method.Name;
                    Console.WriteLine("{0}方法错误:{1}", methodName, ex.Message);
                    //如果没有定义异常处理返回值,就直接抛异常
                    if (!invocation.Method.IsDefined(typeof(ExceptionReturnAttribute), false))
                        throw;
                    var ls = invocation.Method.GetCustomAttributes(typeof(ExceptionReturnAttribute), false);
                    if (null == ls || ls.Length <= 0)
                        throw;
    
                    ExceptionReturnAttribute v = (ExceptionReturnAttribute)ls[0];
                    if (null == v.Value && null == v.Type)
                    {
                        invocation.ReturnValue = null;
                        return;
                    }
                    if (null != v.Value)
                    {
                        invocation.ReturnValue = v.Value;
                        return;
                    }
                    if (null != v.Type)
                    {
                        invocation.ReturnValue = Activator.CreateInstance(v.Type);
                        return;
                    }
                }
            }
    
            /// <summary>
            /// <para>DAO层异常时,不throw,返回设定的值.</para>
            /// <para>1. 返回复杂类型,使用Type,复杂类型需要有无参的构造函数</para>
            /// <para>2. 返回简单类型,使用value</para>
            /// </summary>
            [AttributeUsage(AttributeTargets.Method)]
            public class ExceptionReturnAttribute : System.Attribute
            {
                /// <summary>
                /// 返回复杂类型,使用Type,复杂类型需要有无参的构造函数
                /// </summary>
                public Type Type { get; set; }
    
                /// <summary>
                /// 返回简单类型,使用value
                /// </summary>
                public object Value { get; set; }
            }
        }
    }

    2. 创建拦截容器

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Castle.DynamicProxy;
    
    namespace CastleDEMO
    {
        /// <summary>
        /// Dao 类的接口
        /// 继承实现BaseDao的类,其相关接口访问的公共方法必须要声明 virtual 方法才能被拦截器拦截。
        /// </summary>
        public abstract class BaseDao
        {
           
        }
    
        /// <summary>
        /// Dao容器,必须依赖于此类来创建Dao对象,使Dao受控,可进行检查等
        /// </summary>
        public class DaoContainer
        {
            //ProxyGenerator上自身有缓存
            //实例化【代理类生成器】 
            public static ProxyGenerator generator = new ProxyGenerator();
            public static T GetDao<T>() where T : BaseDao
            {
                //实例化【拦截器】 
                DA_LogInterceptor interceptor = new DA_LogInterceptor();
                //使用【代理类生成器】创建T对象,而不是使用new关键字来实例化 
                return generator.CreateClassProxy<T>(interceptor);
            }
        }
    }

    3. 新建实例类

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace CastleDEMO
    {
        public abstract class PersonDAL : BaseDao
        {
            /// <summary>
            /// 必须是虚方法才能被拦截器拦截
            /// </summary>
            public virtual void SayHello()
            {
                Console.WriteLine("我是虚方法{0}方法", "SayHello");
            }
            public virtual void SayName(string name)
            {
                Console.WriteLine("我是虚方法{0}方法,参数值:{1}", "SayName", name);
            }
            public abstract void AbstactSayOther();
            public void SayOther()
            {
                Console.WriteLine("我是普通方法{0}方法", "SayOther");
            }
        }
    }

    4. 测试

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace CastleDEMO
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                PersonDAL person = DaoContainer.GetDao<PersonDAL>();
                Console.WriteLine("当前类型:{0},父类型:{1}", person.GetType(), person.GetType().BaseType);
                Console.WriteLine();
                person.SayHello();//拦截
                Console.WriteLine();
                person.SayName("Never、C");//拦截
                Console.WriteLine();
                person.SayOther();//普通方法,无法拦截    
                //person.AbstactSayOther();//抽象方法,可以拦截(但是如果方法没实现拦截时会报错)     
                Console.ReadLine();
            }
        }
    }

  • 相关阅读:
    Vue实战笔记
    项目随笔
    Vuex数据可视化
    Vue项目中,要保证某个部分的高度,应该怎么设置
    (转)http authorization 基本认证
    多页应用和单页应用
    Vue项目中使用webpack配置了别名,引入的时候报错
    [转载]解决在win10中webstrom无法使用命令行(Terminal)
    (转)巧用可视区域
    前端管理后台集成解决方案---vue-element-admin
  • 原文地址:https://www.cnblogs.com/li150dan/p/10071775.html
Copyright © 2011-2022 走看看