Heim  >  Artikel  >  Backend-Entwicklung  >  C# Advanced Series – AOP? AOP!

C# Advanced Series – AOP? AOP!

黄舟
黄舟Original
2017-02-07 15:40:111508Durchsuche

Vorwort: In diesem Artikel geht es um AOP. Tatsächlich ist der Blogger erst seit einigen Monaten mit diesem Konzept vertraut Basieren auf AOP, beispielsweise auf der MVC-Filterung. Die darin enthaltenen Ausnahmen können über FilterAttribute und IExceptionFilter verarbeitet werden. Das interne Prinzip des Verarbeitungsmechanismus dieser beiden Objekte sollte AOP sein, aber zuvor gab es kein solches Konzept.


1. AOP-Konzept


Alte Regeln, schauen wir uns zuerst die offizielle Erklärung an: AOP ( Aspektorientierte Programmierung (aspektorientierte Programmierung) ist eine Technologie, die dem Programm dynamisch und einheitlich Funktionen hinzufügen kann, ohne den Quellcode durch dynamische Agenten vor der Kompilierung und zur Laufzeit zu ändern. Es handelt sich um eine neue Methodik, die die traditionelle OOP-Programmierung ergänzt. OOP konzentriert sich darauf, erforderliche Funktionen in verschiedene und relativ unabhängige, gut gekapselte Klassen zu unterteilen und ihnen ein eigenes Verhalten zu ermöglichen, wobei sie sich auf Vererbung und Polymorphismus verlässt, um ihre Beziehungen zu definieren. AOP hofft, in der Lage zu sein, allgemeine erforderliche Funktionen von verwandten Klassen zu trennen ermöglicht es vielen Klassen, ein Verhalten zu teilen. Sobald eine Änderung auftritt, müssen nicht viele Klassen, sondern nur das Verhalten geändert werden. AOP nutzt Aspekte, um Querschnittsthemen zu modularisieren, und OOP nutzt Klassen, um Zustand und Verhalten zu modularisieren. In der OOP-Welt werden Programme durch Klassen und Schnittstellen organisiert, und es ist sehr sinnvoll, sie zur Implementierung der Kerngeschäftslogik des Programms zu verwenden. Es ist jedoch sehr schwierig, übergreifende Anliegen (funktionale Anforderungen, die mehrere Module der Anwendung umfassen) wie Protokollierung, Berechtigungsüberprüfung, Ausnahmeabfangen usw. umzusetzen.


Das Verständnis des Bloggers: AOP extrahiert allgemeine Funktionen. Wenn sich die Anforderungen für allgemeine Funktionen in Zukunft ändern, müssen Sie nur den Code der gemeinsamen Module ändern muss nicht geändert werden. Die sogenannte Aspektorientierung bedeutet, dass wir uns nur auf allgemeine Funktionen und nicht auf die Geschäftslogik konzentrieren. Die Umsetzung erfolgt im Allgemeinen durch Abfangen. Beispielsweise verfügt jedes unserer Webprojekte grundsätzlich über eine Berechtigungsüberprüfungsfunktion. Vor dem Aufrufen jeder Seite wird überprüft, ob der aktuell angemeldete Benutzer über die Berechtigung zum Anzeigen der Schnittstelle verfügt. Es ist uns nicht möglich, diesen Absatz in der Initialisierungsmethode zu schreiben Auf jeder Seite kommt unser AOP zum Einsatz. Der Mechanismus von AOP besteht darin, eine Reihe von Merkmalen vorab zu definieren, damit Sie die gewünschten Geschäfte abfangen können Nachdem wir die Methode ausgeführt haben und sie verwenden, müssen wir nur eine bestimmte Funktion zur entsprechenden Methoden- oder Klassendefinition hinzufügen.


2. Vorteile der Verwendung von AOP

Der Blogger ist der Meinung, dass sich seine Vorteile hauptsächlich in Folgendem widerspiegeln:

1. Trennen Sie allgemeine Funktionen von geschäftlichen Durch das Extrahieren der Logik kann eine große Menge wiederholter Codes weggelassen werden, was sich positiv auf den Betrieb und die Wartung des Codes auswirkt.

2. Beim Entwerfen von Software trägt das Extrahieren gemeinsamer Funktionen (Aspekte) zur Modularisierung des Softwaredesigns bei und verringert die Komplexität der Softwarearchitektur. Mit anderen Worten, die allgemeinen Funktionen sind ein separates Modul, und die Designcodes für diese allgemeinen Funktionen sind nicht im Hauptgeschäft des Projekts zu sehen.

3. Einfache Anwendung von AOP

Um das Funktionsprinzip von AOP zu erklären, möchte der Blogger mit einem einfachen Beispiel beginnen, um zu verstehen, wie AOP durch statisches Abfangen funktioniert.

1. Statisches Abfangen

public class Order
{
    public int Id { set; get; }
    public string Name { set; get; }
    public int Count { set; get; }
    public double Price { set; get; }
    public string Desc { set; get; }
}
 
public interface IOrderProcessor
{
    void Submit(Order order);
}
public class OrderProcessor : IOrderProcessor
{
    public void Submit(Order order)
    {
        Console.WriteLine("提交订单");
    }
}
 
public class OrderProcessorDecorator : IOrderProcessor
{
    public IOrderProcessor OrderProcessor { get; set; }
    public OrderProcessorDecorator(IOrderProcessor orderprocessor)
    {
        OrderProcessor = orderprocessor;
    }
    public void Submit(Order order)
    {
        PreProceed(order);
        OrderProcessor.Submit(order);
        PostProceed(order);
    }
    public void PreProceed(Order order)
    {
        Console.WriteLine("提交订单前,进行订单数据校验....");
        if (order.Price 0)
        {
            Console.WriteLine("订单总价有误,请重新核对订单。");
        }
    }
 
    public void PostProceed(Order order)
    {
        Console.WriteLine("提交带单后,进行订单日志记录......");
        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "提交订单,订单名称:" + order.Name + ",订单价格:" + order.Price);
    }
}

Anrufcode:

static void Main(string[] args)
   {
       Order order = new Order() { Id = 1, Name = "lee", Count = 10, Price = 100.00, Desc = "订单测试" };
       IOrderProcessor orderprocessor = new OrderProcessorDecorator(new OrderProcessor());
       orderprocessor.Submit(order);
       Console.ReadLine();
   }

Ergebnis abrufen:

C# Advanced Series – AOP? AOP!

上面我们模拟订单提交的例子,在提交一个订单前,我们需要做很多的准备工作,比如数据有效性校验等;订单提交完成之后,我们还需要做日志记录等。上面的代码很简单,没有任何复杂的逻辑,从上面的代码可以看出,我们通过静态植入的方式手动在执行方法前和执行方法后让它做一些我们需要的功能。AOP的实现原理应该也是如此,只不过它帮助我们做了方法拦截,帮我们省去了大量重复代码,我们要做的仅仅是写好拦截前和拦截后需要处理的逻辑。


2、动态代理

了解了静态拦截的例子,你是否对AOP有一个初步的认识了呢。下面我们就来到底AOP该如何使用。按照园子里面很多牛人的说法,AOP的实现方式大致可以分为两类:动态代理和IL 编织两种方式。博主也不打算照本宣科,分别拿Demo来说话吧。下面就以两种方式各选一个代表框架来说明。

动态代理方式,博主就以微软企业库(MS Enterprise Library)里面的PIAB(Policy Injection Application Block)框架来作说明。

首先需要下载以下几个dll,然后添加它们的引用。

C# Advanced Series – AOP? AOP!

然后定义对应的Handler

public class User
 {
     public string Name { set; get; }
     public string PassWord { set; get; }
 }
 
 #region 1、定义特性方便使用
 public class LogHandlerAttribute : HandlerAttribute
 {
     public string LogInfo { set; get; }
     public int Order { get; set; }
     public override ICallHandler CreateHandler(IUnityContainer container)
     {
         return new LogHandler() { Order = this.Order, LogInfo = this.LogInfo };
     }
 }
 #endregion
 
 #region 2、注册对需要的Handler拦截请求
 public class LogHandler : ICallHandler
 {
     public int Order { get; set; }
     public string LogInfo { set; get; }
 
     
//这个方法就是拦截的方法,可以规定在执行方法之前和之后的拦截
     public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
     {
         Console.WriteLine("LogInfo内容" + LogInfo);
         
//0.解析参数
         var arrInputs = input.Inputs;
         if (arrInputs.Count > 0)
         {
             var oUserTest1 = arrInputs[0] as User;
         }
         
//1.执行方法之前的拦截
         Console.WriteLine("方法执行前拦截到了");
         
//2.执行方法
         var messagereturn = getNext()(input, getNext);
 
         
//3.执行方法之后的拦截
         Console.WriteLine("方法执行后拦截到了");
         return messagereturn;
     }
 }
 #endregion
 
 #region 3、用户定义接口和实现
 public interface IUserOperation
 {
     void Test(User oUser);
     void Test2(User oUser, User oUser2);
 }
 
 
//这里必须要继承这个类MarshalByRefObject,否则报错
 public class UserOperation : MarshalByRefObject, IUserOperation
 {
     private static UserOperation oUserOpertion = null;
     public UserOperation()
     {
         
//oUserOpertion = PolicyInjection.Create();
     }
 
     
//定义单例模式将PolicyInjection.Create()产生的这个对象传出去,这样就避免了在调用处写这些东西
     public static UserOperation GetInstance()
     {
         if (oUserOpertion == null)
             oUserOpertion = PolicyInjection.Create();
 
         return oUserOpertion;
     }
     
//调用属性也会拦截
     public string Name { set; get; }
 
     
//[LogHandler],在方法上面加这个特性,只对此方法拦截
     [LogHandler(LogInfo = "Test的日志为aaaaa")]
     public void Test(User oUser)
     {
         Console.WriteLine("Test方法执行了");
     }
 
     [LogHandler(LogInfo = "Test2的日志为bbbbb")]
     public void Test2(User oUser, User oUser2)
     {
         Console.WriteLine("Test2方法执行了");
     }
 }
 #endregion

最后我们来看调用的代码:

static void Main(string[] args)
{
    try
    {
        var oUserTest1 = new User() { Name = "test2222", PassWord = "yxj" };
        var oUserTest2 = new User() { Name = "test3333", PassWord = "yxj" };
        var oUser = UserOperation.GetInstance();
        oUser.Test(oUserTest1);
        oUser.Test2(oUserTest1,oUserTest2);
    }
    catch (Exception ex)
    {
        
//throw;
    }
}

得到结果如下:

C# Advanced Series – AOP? AOP!

我们来看执行Test()方法和Test2()方法时候的顺序。

C# Advanced Series – AOP? AOP!

由于Test()和Test2()方法上面加了LogHander特性,这个特性里面定义了AOP的Handler,在执行Test和Test2方法之前和之后都会进入Invoke()方法里面。其实这就是AOP的意义所在,将切面的通用功能在统一的地方处理,在主要逻辑里面直接用过特性使用即可。


3、IL编织

静态织入的方式博主打算使用PostSharp来说明,一来这个使用起来简单,二来项目中用过这种方式。

Postsharp从2.0版本就开始收费了。为了说明AOP的功能,博主下载了一个免费版本的安装包,使用PostSharp与其它框架不太一样的是一定要下载安装包安装,只引用类库是不行的,因为上文说过,AOP框架需要为编译器或运行时添加扩展。使用步骤如下:

(1)下载Postsharp安装包,安装。

(2)在需要使用AOP的项目中添加PostSharp.dll 这个dll的引用。

(3)定义拦截的方法:

[Serializable]
public class TestAop : PostSharp.Aspects.OnMethodBoundaryAspect
{     
//发生异常时进入此方法
    public override void OnException(MethodExecutionArgs args)
    {
        base.OnException(args);
    }
 
//执行方法前执行此方法
    public override void OnEntry(MethodExecutionArgs args)
    {
        base.OnEntry(args);
    }
 
//执行方法后执行此方法
    public override void OnExit(MethodExecutionArgs args)
    {
        base.OnExit(args);
    }
}

注意这里的TestAop这个类必须要是可序列化的,所以要加上[Serializable]特性

(4)在需要拦截功能的地方使用。

在类上面加特性拦截,此类下面的所有的方法都会具有拦截功能。

[TestAop]public class Impc_TM_PLANT : Ifc_TM_PLANT
  {
      /// 
      /// 获取或设置服务接口。
      /// 
      private Ic_TM_PLANTService service { get; set; }
 
      public IList Find()
      {
          DTO_TM_PLANT otest = null;
          otest.NAME_C = "test";
            //异常,会进入OnException方法
      return service.FindAll();   
   }  
}

方法上面加特性拦截,只会拦截此方法。

[TestAop]
public IList Find()
{
    DTO_TM_PLANT otest = null;
    otest.NAME_C = "test";
    return service.FindAll();
}

有没有感觉很简单,很强大,其实这一简单应用,解决我们常见的日志、异常、权限验证等功能简直太小菜一碟了。当然Postsharp可能还有许多更加高级的功能,有兴趣可以深究下。

4、MVC里面的Filter

public class AOPFilterAttribute : ActionFilterAttribute, IExceptionFilter
 {
 
     public void OnException(ExceptionContext filterContext)
     {
         throw new System.NotImplementedException();
     }
     public override void OnActionExecuting(ActionExecutingContext filterContext)
     {
 
         base.OnActionExecuting(filterContext);
     }
 
     public override void OnActionExecuted(ActionExecutedContext filterContext)
     {
         base.OnActionExecuted(filterContext);
     }
 }

在controller里面使用该特性:

[AOPFilter]
   public JsonResult GetEditModel(string strType)
   {
       var lstRes = new List>();
       var lstResPage = new List();        
//.........todo
 
       return Json(new { lstDataAttr = lstRes, PageAttr = lstResPage, lstJsConnections = lstJsPlumbLines }, JsonRequestBehavior.AllowGet);
   }

调试可知,在执行GetEditModel(string strType)方法之前,会先执行OnActionExecuting()方法,GetEditModel(string strType)之后,又会执行OnActionExecuted()方法。这在我们MVC里面权限验证、错误页导向、日志记录等常用功能都可以方便解决。

Das Obige ist die C#-Erweitertserie – AOP? AOP! Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php.cn)!


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn