在上一节,我们将静态实现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. yii2:多条件多where条件下碰到between时,between语句如何处理呢?

    yii2:多条件多where条件下碰到between时,between语句如何处理呢? 我有一张表:id,name,telphone,ticket_no,status,create_time等字段, ...

  2. C++(十五) — sizeof 运算符

    1.基本数据类型 sizeof 是一个关键字,它是一个编译时运算符,用于判断变量或数据类型的字节大小. sizeof 运算符可用于获取类.结构.共用体和其他用户自定义数据类型的大小. 使用 sizeo ...

  3. HBase Cassandra比较

    转自:http://itindex.net/detail/22338-cassandra-hbase-%E8%AE%BE%E8%AE%A1     Cassandra HBase 一致性 Quorum ...

  4. Struts02---实现struts2的三种方式

    01.创建普通类 /** * 01.普通类 * 写一个execute() 返回String类型值 * */ public class HelloAction01 { public String exe ...

  5. xhtml html

    xhtml是用xml语言重写了html,相比html更规范了, XHTML是HTML像XML的一个过渡语言,它比HTML严谨性会高点,然后基本语言都还是沿用的HTML的标签,只不过废除了部分表现层的标 ...

  6. HAWQ取代传统数仓实践(十)——维度表技术之杂项维度

    一.什么是杂项维度 简单地说,杂项维度就是一种包含的数据具有很少可能值的维度.事务型商业过程通常产生一系列混杂的.低基数的标志位或状态信息.与其为每个标志或属性定义不同的维度,不如建立单独的将不同维度 ...

  7. wordpress 使用固定链接

    官方文档 无插件移除url中category 目录前缀 设置 >> 固定链接,设置固定链接为自定义为: /%category%/%postname%/或者/%category%/%post ...

  8. 瀑布流下滑 发送ajax

    <!DOCTYPE=html>      <html>      <head>      <meta charset="UTF-8"> ...

  9. python Beautiful Soup的使用

    上一节我们介绍了正则表达式,它的内容其实还是蛮多的,如果一个正则匹配稍有差池,那可能程序就处在永久的循环之中,而且有的小伙伴们也对写正则表 达式的写法用得不熟练,没关系,我们还有一个更强大的工具,叫B ...

  10. Ubuntu15.10下Hadoop2.6.0伪分布式环境安装配置及Hadoop Streaming的体验

    Ubuntu用的是Ubuntu15.10Beta2版本,正式的版本好像要到这个月的22号才发布.参考的资料主要是http://www.powerxing.com/install-hadoop-clus ...