在上一节,我们将静态实现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. activity启动模式之standard

    activity启动模式之standard 一.简介 这种模式是默认的,不用我们自己设定 就像一只叠加在栈中 如果退出,就一个个退出,其实就是我们自己用手机的那种感受 二.代码实例 activityL ...

  2. spirng: srping mvc配置(访问路径配置)搭建SpringMVC——最小化配置

    搭建SpringMVC——最小化配置 最开始接触网页的时候,是纯的html/css页面,那个时候还是用Dreamweaver来绘制页面. 随着网站开发的深入,开始学习servlet开发,记得最痛苦的就 ...

  3. 【Demo】CSS3 3D转换

    3D转换transform rotateX() 方法 rotateX()方法,围绕其在一个给定度数X轴旋转的元素. div { transform: rotateX(120deg); -webkit- ...

  4. 51nod 1486

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1486 1486 大大走格子 题目来源: CodeForces 基准时间限 ...

  5. jQUery 样式操作

    一.css样式操作的方法: 1..css("样式"):获得样式值,比如$("input").css("color")  获得input中字体 ...

  6. Django框架(三)

    0627内容: 上节回顾: 1. FBV.CBV 2. 数据库操作 class UserGroup(models.Model): """ 部门 3 "" ...

  7. java基本数据类型、修饰符、运算符

    数据类型: 基本数据类型 整数类型  byte,8位  short,16位  int,32位i  long,64位 浮点类型  float,单精度,32位  double,双精度,64位 布尔类型   ...

  8. CSS:Tutorial four

    1.CSS Tables To specify table borders in CSS, use the border property. The example below specifies a ...

  9. 20165210 Java第五次实验报告

    20165210 实验五 网络编程与安全 网络编程与安全一: 实验要求: 两人一组结对编程: 参考http://www.cnblogs.com/rocedu/p/6766748.html#SECDSA ...

  10. keras 入门模型训练

    # -*- coding: utf-8 -*- from keras.models import Sequential from keras.layers import Dense from kera ...