聊一下Castle DynamicProxy基本用法(AOP)

服务器
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

[[408194]]

 本文转载自微信公众号「UP技术控」,作者conan5566。转载本文请联系UP技术控公众号。

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点……是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

动态代理是实现AOP的一种方式,即在开发过程中我们不需要处理切面中(日志等)的工作,而是在运行时,通过动态代理来自动完成。Castle DynamicProxy是一个实现动态代理的框架,被很多优秀的项目用来实现AOP编程,EF Core、Autofac等。

为业务类添加AOP拦截器

/// <summary> 
  /// 为业务类添加AOP拦截器。 
  /// </summary> 
  public class InterceptorAttribute:PlutoStudio.Aop.InterceptorAttribute 
  { 
      /// <summary> 
      /// 拦截方法的执行,如果当前方法有拦截处理器,则执行处理器。 
      /// </summary> 
      /// <param name="invocation">被拦截的调用目标对象</param> 
      public override void Intercept(IInvocation invocation) 
      { 
          var method = invocation.Method; 
          var processors = method.GetCustomAttributes(typeof(IInterceptorProcessor),true).Cast<IInterceptorProcessor>().ToList(); 
          processors.ForEach(p => PlutoStudio.MefContainer.Container.ComposeParts(p)); 
          if (processors.Count>0) 
          { 
              processors.ForEach(p => p.PreProcess(invocation)); 
              try 
              { 
                  invocation.Proceed(); 
                  processors.ForEach(p => p.PostProcess(invocation, null)); 
              } 
              catch (Exception ex) 
              { 
                  processors.ForEach(p => p.PostProcess(invocation, ex)); 
                  throw; 
              } 
          } 
          else 
          { 
              invocation.Proceed(); 
          } 
      } 
  } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
/// <summary> 
 /// 拦截器处理器接口。 
 /// </summary> 
 public interface IInterceptorProcessor 
 { 
     /// <summary> 
     /// 拦截器处理方法,在目标方法执行前执行。 
     /// </summary> 
     /// <param name="invocation">拦截的目标对象</param> 
     void PreProcess(IInvocation invocation); 
 
     /// <summary> 
     /// 拦截器处理方法,在目标方法执行后执行。 
     /// </summary> 
     /// <param name="invocation">拦截的目标对象</param> 
     /// <param name="ex">目标方法的异常</param> 
     void PostProcess(IInvocation invocation,Exception ex); 
 } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

日志处理器

可以将目标方法的信息保存到日志系统中

/// <summary> 
  /// 日志处理器,可以将目标方法的信息保存到日志系统中。 
  /// </summary> 
  [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] 
  public class LogAttribute : Attribute, IInterceptorProcessor 
  { 
      [Import(AllowDefault = true)] 
      public ILog Log { get; set; } 
 
      /// <summary> 
      /// 在目标方法执行完成后执行,这里会记录目标方法的相关信息并写入日志系统。 
      /// </summary> 
      /// <param name="invocation"></param> 
      /// <param name="ex"></param> 
      public void PostProcess(IInvocation invocation, Exception ex) 
      { 
          if (Log != null
          { 
              var @class = invocation.TargetType.FullName; 
              var method = invocation.Method.Name
              var parameterNames = invocation.Method.GetParameters().Select(p => p.Name).ToList(); 
              var args = invocation.Arguments; 
              var parameters = new Dictionary<string, object>(); 
              for (int i = 0; i < parameterNames.Count; i++) 
              { 
                  parameters.Add(parameterNames[i], args[i]); 
              } 
              var returnValue = invocation.ReturnValue; 
              var stackTrace = new StackTrace(true); 
              var stacks = stackTrace.GetFrames(); 
              var stack = stacks.SkipWhile(i => i.GetMethod().Name != invocation.Method.Name).Select(GetStack); 
              var log = new TraceLog 
              { 
                  Class = @class, 
                  Method = method, 
                  Parameter = parameters, 
                  ReturnValue = returnValue, 
                  Strack = stack, 
                  Exception = ex, 
              }; 
              Log.Custom(log); 
 
          } 
      } 
 
      private object GetStack(StackFrame frame) 
      { 
          var method = frame.GetMethod(); 
          var type = method.ReflectedType; 
          if (type.FullName.StartsWith("Castle.Proxies")) 
          { 
              type = type.BaseType; 
          } 
          return new 
          { 
              Method = method.Name
              Type = type.FullName, 
              File = frame.GetFileName(), 
              Line = frame.GetFileLineNumber(), 
          }; 
      } 
 
      public void PreProcess(IInvocation invocation) 
      { 
      } 
  } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
/// <summary> 
  /// 系统跟踪日志,由<see cref="LogAttribute"/>生成。 
  /// </summary> 
  public class TraceLog 
  { 
      /// <summary> 
      /// 当前日志记录的目标类。 
      /// </summary> 
      public string Class { get; internal set; } 
      /// <summary> 
      /// 当前日志跟踪到的异常。 
      /// </summary> 
      public Exception Exception { get; internal set; } 
      /// <summary> 
      /// 当前日志记录的目标方法。 
      /// </summary> 
      public string Method { get; internal set; } 
      /// <summary> 
      /// 当前日志记录的目标方法的参数。 
      /// </summary> 
      public Dictionary<string, object> Parameter { get; internal set; } 
      /// <summary> 
      /// 当前日志记录的目标方法的返回值。 
      /// </summary> 
      public object ReturnValue { get; internal set; } 
 
      /// <summary> 
      /// 当前日志记录的目标方法的调用栈。 
      /// </summary> 
      public IEnumerable<object> Strack { get; internal set; } 
  } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.

 

 

责任编辑:武晓燕 来源: UP技术控
相关推荐

2021-04-21 14:19:52

javaignalHandle接口

2025-01-10 11:07:28

2021-04-27 07:52:18

SQLNULLOR

2009-07-20 15:27:22

Castle.DynaiBATIS.NET

2021-04-21 21:06:11

数据结构

2022-02-08 08:31:52

const关键字C语言

2021-03-10 00:02:01

Redis

2021-05-31 06:28:35

AutoMapper对象映射器

2024-10-28 21:02:36

消息框应用程序

2021-03-26 00:20:34

NFT区块链数据库

2021-08-07 07:56:59

Node逻辑对象

2019-01-31 07:16:06

2018-04-25 06:46:52

2021-06-06 12:59:14

实现方式计数

2021-05-12 18:02:23

方法创建线程

2011-08-22 15:19:25

2020-09-29 09:41:50

Spring Boot项目代码

2023-02-09 08:48:47

Java虚拟机

2024-05-29 11:24:27

2015-06-16 13:04:35

C#开发者JAVA 开发者
点赞
收藏

51CTO技术栈公众号