在上一节,我们将静态实现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. 习题-第7章Web自动化测试

    一.选择题 1.如果火狐浏览器不在默认安装路径,编写Selenium的设置代码,横线处应该填入(    ), System.setProperty(“webdriver.firefox._______ ...

  2. java多线程学习三

    本章主要学习线程的静态方法 1.先忙先看一段代码: public class MyThread3 implements Runnable { static { System.out.println(& ...

  3. 状态管理(Vuex、 Flux、Redux、The Elm Architecture)

    1.https://vuex.vuejs.org/zh-cn/intro.html (vuex) 这就是 Vuex 背后的基本思想,借鉴了 Flux.Redux.和 The Elm Architect ...

  4. Installing Forms Developer 10g and Reports 32-bit on 64-bit Windows versions(win7 or win10)

    E-Business Suite 12.1 and 12.2 require Forms Developer 10g and Reports Designer 10g.  Forms Develope ...

  5. [转载]java在线比较两个word文件

    一.项目背景 开发文档管理系统或OA办公系统的时候,实现在线处理word文档的功能比较容易,但是也经常会有客户提出文档版本管理的需求,这就需要同时在线打开两个word文件,对比两个不同版本的word文 ...

  6. 猪齿鱼_01_环境搭建(二)_微服务支撑组件部署(Docker形式)

    一.前言 上一节,我们以源码形式部署好了猪齿鱼微服务组件,过程繁琐,且启动后占用了服务器大量的资源,对开发极其不友好.

  7. LeetCode OJ:Add Two Numbers (相加链表之数)

    You are given two linked lists representing two non-negative numbers. The digits are stored in rever ...

  8. Lua基础---变量与赋值

    看以下案例: test.lua -- 第一个lua脚本 --注释使用"--"符 --变量未定义时,默认初始化的值为nil --这样的定义为全局 num1 = 1 ; --加了关键字 ...

  9. Android 如何快速生成aar?

    aar主要分为两步 第一步 新建一个Module类似于Eclipse中的project 然后AddLibrary然后点击Finish完成 生成mylibrary-debug.aar文件 然后将.aar ...

  10. Windows10重启之后总是将默认浏览器设置为IE

    换了一台电脑之后,发现系统重启之后总是会把我的默认浏览器设置为IE,而自从用上了Chrome,我对他爱不释手. 上网找了不少文章,都建议使用系统自带的设置进行默认浏览器的设置,试了三四次,完全不起任何 ...