在上一节,我们将静态实现AOP,但是对于一个大型项目,要想为每个类,每个方法都去实现AOP ,进行日志记录和权限验证似乎是不可能的。 即使可能对于成百上千个类维护,也是很难维护。所以今天的主题就是如标题所述。

(Real Proxy)真正代理和(Dynamic Proxy)动态代理

Real Proxy 类是个抽象类,定义在 System.Runtime.Remoting.Proxies,定义了代理的一些公共的基本的功能方法。

Dynamic Proxy 类必须继承Real Proxy,通过重写它的调用方法和添加新功能来达到目的。那么 Dynamic Proxy 定义如下:

 

class DynamicProxy<T> : RealProxy
    {
      private readonly T _decorated;
      public DynamicProxy(T decorated)
    : base(typeof(T))
      {
    _decorated = decorated;
      }
      private void Log(string msg, object arg = null)
      {
    Console.ForegroundColor = ConsoleColor.Red;
    Console.WriteLine(msg, arg);
    Console.ResetColor();
      }
      public override IMessage Invoke(IMessage msg)
      {
    var methodCall = msg as IMethodCallMessage;
    var methodInfo = methodCall.MethodBase as MethodInfo;
    Log("In Dynamic Proxy - Before executing '{0}'",
      methodCall.MethodName);
    try
    {
      var result = methodInfo.Invoke(_decorated, methodCall.InArgs);
      Log("In Dynamic Proxy - After executing '{0}' ",
    methodCall.MethodName);
      return new ReturnMessage(result, null, 0,
    methodCall.LogicalCallContext, methodCall);
    }
    catch (Exception e)
    {
     Log(string.Format(
       "In Dynamic Proxy- Exception {0} executing '{1}'", e),
       methodCall.MethodName);
     return new ReturnMessage(e, methodCall);
    }
      }
    }

为此,我们已经定义好了动态代理类,但是为了使用包装者Repository<T>类, 必须还得使用GetTransparentProxy(他返回一个 IRepository<Customer>实例)方法,每一个方实例的方法的调用将通过代理来调用,也就是说,你可以定义一个Factory 来创建 proxy和返回泛型Repository<T>实例。所以代码类似于定义如下:

 

public class RepositoryFactory
    {
      public static IRepository<T> Create<T>()
      {
    var repository = new Repository<T>();
    var dynamicProxy = new DynamicProxy<IRepository<T>>(repository);
    return dynamicProxy.GetTransparentProxy() as IRepository<T>;
      }
    }

 

接下来,编写控制台代码 大概如下:

    static void Main(string[] args)
    {
      Console.WriteLine("***\r\n Begin program - logging with dynamic proxy\r\n");
      // IRepository<Customer> customerRepository =
      //   new Repository<Customer>();
      // IRepository<Customer> customerRepository =
      //   new LoggerRepository<Customer>(new Repository<Customer>());
      IRepository<Customer> customerRepository =
    RepositoryFactory.Create<Customer>();
      var customer = new Customer
      {
    Id = 1,
    Name = "Customer 1",
    Address = "Address 1"
       ;
      customerRepository.Add(customer);
      customerRepository.Update(customer);
      customerRepository.Delete(customer);
      Console.WriteLine("\r\nEnd program - logging with dynamic proxy\r\n***");
      Console.ReadLine();
    }

 

运行结果,如下:

正如你所看到的,你已经创建一个动态代理,允许添加AOP代码,不需要重复。如果你想添加一个新的方面,现在你只需要创建一个新的类,继承Real Proxy并使用它来装饰第一个代理。如果你的老板要你,要求你添加授权代码,并且只有管理员才可以访问存储库,您可以创建一个新的代理,代码如下:

 

class AuthenticationProxy<T> : RealProxy
    {
      private readonly T _decorated;
      public AuthenticationProxy(T decorated)
    : base(typeof(T))
      {
    _decorated = decorated;
      }
      private void Log(string msg, object arg = null)
      {
    Console.ForegroundColor = ConsoleColor.Green;
    Console.WriteLine(msg, arg);
    Console.ResetColor();
      }
      public override IMessage Invoke(IMessage msg)
      {
    var methodCall = msg as IMethodCallMessage;
    var methodInfo = methodCall.MethodBase as MethodInfo;
    if (Thread.CurrentPrincipal.IsInRole("ADMIN"))
    {
      try
      {
    Log("User authenticated - You can execute '{0}' ",
      methodCall.MethodName);
    var result = methodInfo.Invoke(_decorated, methodCall.InArgs);
    return new ReturnMessage(result, null, 0,
      methodCall.LogicalCallContext, methodCall);
      }
      catch (Exception e)
      {
    Log(string.Format(
      "User authenticated - Exception {0} executing '{1}'", e),
      methodCall.MethodName);
    return new ReturnMessage(e, methodCall);
      }
    }
    Log("User not authenticated - You can't execute '{0}' ",
      methodCall.MethodName);
    return new ReturnMessage(null, null, 0,
      methodCall.LogicalCallContext, methodCall);
      }
    }

所以repository工厂必须更改实现两个代理,代码如下:

    public class RepositoryFactory
    {
      public static IRepository<TCreate<T>()
      {
    var repository = new Repository<T>();
    var decoratedRepository =
      (IRepository<T>)new DynamicProxy<IRepository<T>>(
      repository).GetTransparentProxy();
    // Create a dynamic proxy for the class already decorated
    decoratedRepository =
      (IRepository<T>)new AuthenticationProxy<IRepository<T>>(
      decoratedRepository).GetTransparentProxy();
    return decoratedRepository;
      }
    }

控制台程序,需要更改代码,如下所示:

    static void Main(string[] args)
    {
      Console.WriteLine(
    "***\r\n Begin program - logging and authentication\r\n");
      Console.WriteLine("\r\nRunning as admin");
      Thread.CurrentPrincipal =
    new GenericPrincipal(new GenericIdentity("Administrator"),
    new[] { "ADMIN" });
      IRepository<Customer> customerRepository =
    RepositoryFactory.Create<Customer>();
      var customer = new Customer
      {
    Id = 1,
    Name = "Customer 1",
    Address = "Address 1"
      };
      customerRepository.Add(customer);
      customerRepository.Update(customer);
      customerRepository.Delete(customer);
      Console.WriteLine("\r\nRunning as user");
      Thread.CurrentPrincipal =
    new GenericPrincipal(new GenericIdentity("NormalUser"),
    new string[] { });
      customerRepository.Add(customer);
      customerRepository.Update(customer);
      customerRepository.Delete(customer);
      Console.WriteLine(
    "\r\nEnd program - logging and authentication\r\n***");
      Console.ReadLine();
    }

 

运行结果如下

到此为止就 全部实现动态代理实现AOP.

下一节,我们讲继续讲Aop之方法过滤。

AOP参考

本文翻译自 :https://msdn.microsoft.com/en-us/magazine/dn574804.aspx(面向切面编程)

.Net 框架实现AOP(动态代理实现AOP,本文为翻译)的更多相关文章

  1. .NET 下基于动态代理的 AOP 框架实现揭秘

    .NET 下基于动态代理的 AOP 框架实现揭秘 Intro 之前基于 Roslyn 实现了一个简单的条件解析引擎,想了解的可以看这篇文章 https://www.cnblogs.com/weihan ...

  2. 动态代理的两种方式,以及区别(静态代理、JDK与CGLIB动态代理、AOP+IoC)

    Spring学习总结(二)——静态代理.JDK与CGLIB动态代理.AOP+IoC   目录 一.为什么需要代理模式 二.静态代理 三.动态代理,使用JDK内置的Proxy实现 四.动态代理,使用cg ...

  3. 技术的正宗与野路子 c#, AOP动态代理实现动态权限控制(一) 探索基于.NET下实现一句话木马之asmx篇 asp.net core 系列 9 环境(Development、Staging 、Production)

    黄衫女子的武功似乎与周芷若乃是一路,飘忽灵动,变幻无方,但举手抬足之间却是正而不邪,如说周芷若形似鬼魅,那黄衫女子便是态拟神仙. 这段描写出自<倚天屠龙记>第三十八回. “九阴神抓”本是& ...

  4. Java动态代理-->Spring AOP

    引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓“登高必自卑,涉远必自迩”.以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系列分别介绍这些Jav ...

  5. Spring学习笔记之aop动态代理(3)

    Spring学习笔记之aop动态代理(3) 1.0 静态代理模式的缺点: 1.在该系统中有多少的dao就的写多少的proxy,麻烦 2.如果目标接口有方法的改动,则proxy也需要改动. Person ...

  6. DispatchProxy实现动态代理及AOP

    DispatchProxy类是DotnetCore下的动态代理的类,源码地址:Github,官方文档:MSDN.主要是Activator以及AssemblyBuilder来实现的(请看源码分析),园子 ...

  7. Java 动态代理与AOP

    动态代理与AOP 代理模式 代理模式给某一个目标对象(target)提供代理对象(proxy),并由代理对象控制对target对象的引用. 模式图: 代理模式中的角色有: 抽象对象角色(Abstrac ...

  8. Java 动态代理及AOP实现机制

    AOP实现机制http://www.iteye.com/topic/1116696 AOP: (Aspect Oriented Programming) 面向切面编程AOP包括切面(aspect).通 ...

  9. 实现一个简单的基于动态代理的 AOP

    实现一个简单的基于动态代理的 AOP Intro 上次看基于动态代理的 AOP 框架实现,立了一个 Flag, 自己写一个简单的 AOP 实现示例,今天过来填坑了 目前的实现是基于 Emit 来做的, ...

随机推荐

  1. 第二章 Burp Suite代理和浏览器设置

    Burp Suite代理工具是以拦截代理的方式,拦截所有通过代理的网络流量,如客户端的请求数据.服务器端的返回信息等.Burp Suite主要拦截http和https协议的流量,通过拦截,Burp S ...

  2. Educational Codeforces Round 27

    期末后恢复性训练,结果完美爆炸... A,题意:2n个人,分成两队,要求无论怎么分配,第一队打赢第二队 #include<bits/stdc++.h> #define fi first # ...

  3. @ResponseBody与@RestController的作用与区别

    在使用springmvc框架的时候,在处理json的时候需要用到spring框架特有的注解@ResponseBody或者@RestController注解,这两个注解都会处理返回的数据格式,使用了该类 ...

  4. N!含有多少个 2/5质因子

    编程之美127页,N!中含有质因数2的个数 = [N/2] + [N/4] + [N/8] + [N/16] + ..... 要理解上式,先看 编程之美126页,N!中含有质因数5的个数Z 举例:N ...

  5. 使用VS自带的工具分析.NET程序的性能

    (转自:http://www.cnblogs.com/DebugLZQ/archive/2012/07/10/2585245.html) 这篇博文给大家分享的是,如何使用VS自带的性能分析工具来分析我 ...

  6. 服务器(Ubuntu 12.04 LTS)上编译基于OpenCV的项目遇到的问题及解决方案

    问题1:OpenCV编译安装时出错,错误信息中提到要打开-fPIC 选项重试. 解决方案:使用如下命令运行CMake cmake -DWITH_1394=OFF -DWITH_CUDA=OFF -DW ...

  7. 【Codeforces】894D. Ralph And His Tour in Binary Country 思维+二分

    题意 给定一棵$n$个节点完全二叉树,$m$次询问,每次询问从$a$节点到其它所有节点(包括自身)的距离$L$与给定$H_a$之差$H_a-L$大于$0$的值之和 对整棵树从叶子节点到父节点从上往下预 ...

  8. L145

    实践是检验真理的唯一标准.Only social practice can be the criterion of truth.工会负责人谴责这一行动破坏了协议.Union officials den ...

  9. New Concept English three (30)

    27W/m 32 words the death of ghost For years, villagers believed that Endley Farm was hunted. The far ...

  10. 不用配置 , 快速搭建react环境

    链接 create-react-app react-webpack-generators react-cli