Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the programming idea of AOP in C #

2025-02-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article is to share with you about what AOP programming ideas are in C#. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.

What is AOP

The abbreviation of AOP:Aspect Oriented Programming means a technology for aspect-oriented programming to realize the unified maintenance of program functions through pre-compilation and dynamic agents during operation. AOP is the continuation of OOP's thought. Each part of the business logic can be isolated by using AOP, which reduces the coupling between the various parts of the business logic, improves the reusability of the program, and improves the efficiency of development at the same time.

Why do you want to learn AOP?

The application scenario of AOP is very extensive, and it appears frequently in the interview process of some senior engineers or architects.

Second, the development route of programming ideas. 1. POP

The abbreviation of POP:Procedure Oriented Programming, that is, process-oriented programming, is a process-centered programming idea.

Process-oriented is to analyze the steps to solve the problem, and then use functions or methods to implement these steps step by step, and use them to call functions or methods one by one, which is process-oriented programming. In the beginning, it was all process-oriented programming. Process-oriented is the most practical way of thinking. Even object-oriented programming contains the idea of process-oriented programming, because process-oriented programming is a basic way of programming thinking, it starts from reality to consider how to achieve requirements.

The deficiency of POP: process-oriented programming can only deal with some simple problems, but can not deal with some complex problems. If the problem is very complex and all think in terms of the process, you will find that the process is very chaotic and even the process can't go on.

2 、 OOP

The abbreviation of OOP:Object Oriented Programming is object-oriented programming.

Early computer programming was process-oriented because early programming was relatively simple. However, with the development of time, there are more and more problems to be dealt with, and the problems will become more and more complex. At this time, we can not simply use process-oriented programming, so object-oriented programming appears. In a computer, think of everything as one thing. Objects in the real world have some properties and behaviors, which correspond to properties and methods in the computer.

Object-oriented programming is to decompose the things that make up the problem into objects, the purpose of which is not to complete a step, but to describe the behavior of something in the whole step of solving the problem.

Let's take a building as an example to illustrate the shortcomings of OOP.

We compare the system to a building, the class or object is bricks, bricks form a wall, multiple walls form a room, and multiple rooms form a building.

It is as if the function of a module is implemented by multiple classes, the module constitutes a service, and multiple services constitute a complete system. The completion of a system development does not mean that it is really completed, and there will certainly be changes in various requirements in the future. After the requirements change appears, you have to modify the code. The code is all in the class, which is equivalent to modifying the class. If it is a small-scale modification, the impact is not great, if it is a large-scale modification, the impact will be greater. Even if each change is small, if you make changes frequently, the impact will be great. It will cause instability in the system. We conclude that classes should be fixed, should not be modified frequently, or even allowed to be modified. This is why there are so many design principles and design patterns. Most design patterns are designed to solve this problem, that is, to extend functionality without modifying the class.

Deficiency of OOP: the generation of new requirements will lead to continuous modification of the program code, which is easy to cause program instability.

If you know a lot about OOP, then we should know that from the point of view of the organization of objects, classification methods are based on inheritance relationships, which we call vertical. If you only use OOP ideas, there are two problems:

1. Common problems.

2. Extension problem, it is more difficult when you need to extend the existing class.

The difference between OOP and POP:

When comparing process-oriented, the object-oriented approach is to minimize things to objects, including properties and methods. When the scale of the program is relatively small, process-oriented programming still has some advantages, because at this time the flow of the program is relatively easy to sort out. Take going to work in the morning as an example, the process is to get up, get dressed, brush your teeth and wash your face, and go to the office. Each step is completed in order, we just need to follow the steps to implement the method step by step, and finally call the implementation method in turn, which is process-oriented development.

If we use object-oriented programming, we need to abstract an employee class that has four ways to get up, get dressed, brush your teeth and wash your face, and go to the company. However, in the end, if you want to realize the need to go to work in the morning, you still have to call four methods in order. At the beginning, we think about the requirement according to the process-oriented idea, and then abstract several methods according to the object-oriented thought, and finally realize this requirement according to the process-oriented order.

The difference between object-oriented and process-oriented is only in the way of thinking. Eventually you will find that when you implement this requirement, even if you abstract the employee class using the idea of object-oriented, you still have to use process-oriented to implement this requirement.

3 、 AOP

The abbreviation of AOP:Aspect Oriented Programming, that is, aspect-oriented programming. It is a supplement to OOP, a technology to dynamically add unified functions to the program without modifying the original class.

OOP focuses on dividing requirement functions into different and relatively independent, well-encapsulated classes, and relies on inheritance and polymorphism to define the relationship between them. AOP can separate the general requirements function from unrelated classes, and many classes share a behavior. Once there is a change, there is no need to modify many classes, just to modify this one class.

What does the section in AOP mean? A section refers to a crosscutting concern. Look at the following picture:

OOP is designed to modularize state and behavior. The picture above is a shopping mall system, which is vertically divided into order management, commodity management and inventory management modules using OOP. In this system, we need to carry out authorization verification. Such as orders, goods, inventory are business logic functions, but these three modules all need some common functions, such as authorization verification, logging and so on. It is impossible for us to write authorization verification in every module, and authorization verification does not belong to a specific business, it actually belongs to functional modules and spans multiple business modules. You can see that this is horizontal, this is the so-called section. Popular will, AOP is to extract the common functions, if these common functions have changed in the future, we only need to modify the code of these common functions, other places do not need to change. The so-called aspect is to focus only on general functions, not on business logic, and not to modify the original classes.

AOP advantages:

The general function is extracted from the business logic to improve the code reusability, which is beneficial to the later maintenance and expansion.

In software design, the extraction of general functions (aspects) is conducive to the modularization of software design and reduce the complexity of software architecture.

AOP's disadvantages:

AOP is a supplement to the idea of OOP, which cannot exist alone. It is impossible to use AOP alone to design a system. When designing a system, if the system is relatively simple, you can only use POP or OOP to design. If the system is complex, you need to use AOP ideas. First of all, we should use POP to sort out the whole business process, then sort out the classes and modules according to the process of POP, and finally use AOP to extract general functions.

The difference between AOP and OOP:

Goal-oriented is different: OOP is noun-oriented (abstracting something, such as students, employees, these are nouns). AOP is oriented to the verb domain (such as authentication, logging, which are actions or actions).

The ideological structure is different: OOP is vertical (inheritance is the main line, so it is vertical). AOP is horizontal.

Pay attention to different aspects: OOP pays attention to the division of business logic units, while AOP focuses on a certain step or stage in the process of business processing.

The three ideas of POP, OOP and AOP complement each other. In the development process of a system, these three programming ideas are indispensable.

Third, realize AOP

We explained some theoretical knowledge about AOP above, so how to implement it in the code?

There are two ways to implement AOP:

Static proxy implementation. The so-called static proxy is that we write the proxy object ourselves.

Dynamic proxy implementation. The so-called dynamic proxy is to generate a proxy object when the program is running.

1. Static agent

The implementation of static proxy requires the use of two design patterns: decorator mode and proxy mode.

Decorator mode: allows you to add new functionality to an existing object without changing the structure of the existing object. It belongs to structural design pattern, which is a kind of wrapper of existing class. First, a decoration class is created to wrap the original class and provide additional functionality while maintaining the integrity of the class. Look at the following example.

Let's first create a User class:

Using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace StaticDemo.Model {public class User {public string Name {get; set;} public string Password {get; set;}

Then we create an interface for the account service, in which there is a method to register a user:

Using StaticDemo.Model;namespace StaticDemo.Services {/ Interface / public interface IAccountService {/ registered user / void Reg (User user);}}

Then create a class to implement the above interface:

Using StaticDemo.Model;using System;namespace StaticDemo.Services {/ implement IAccountService interface / public class AccountService: IAccountService {public void Reg (User user) {/ / execute some other logical Console.WriteLine before or after the business code ($"{user.Name} registered successfully");}

We are creating a decorator class:

Using StaticDemo.Model;using StaticDemo.Services;using System;namespace StaticDemo {/ decorator class / public class AccountDecorator: IAccountService {private readonly IAccountService _ accountService; public AccountDecorator (IAccountService accountService) {_ accountService = accountService;} public void Reg (User user) {Before () / / the registered method is called here, and the logic in the original class will not change / / add other logic before and after the logic _ accountService.Reg (user); After ();} private void Before () {Console.WriteLine ("logic before registration") } private void After () {Console.WriteLine ("Logic after registration");}

We will find that the decorator class also implements the IAccountService interface. Finally, we call in the Main method:

Using StaticDemo.Model;using StaticDemo.Services;using System;namespace StaticDemo {class Program {static void Main (string [] args) {/ / instantiate the object IAccountService accountService = new AccountService (); / / instantiate the decorator class and pass the value var account = new AccountDecorator (accountService) to the constructor using the above example Var user = new User {Name = "Rick", Password = "12345678"}; / / call the registration method of the decorator class, which is equivalent to calling the registration method account.Reg (user) of the instantiated object; Console.ReadKey ();}

Running result:

Let's take a look at how to use the proxy pattern to implement.

Proxy pattern: that is, the function of one class representing another. We will create a proxy class, which is basically the same as the decorator class. Take a look at the code:

Using StaticDemo.Model;using StaticDemo.Services;using System;namespace StaticDemo {/ proxy class / public class ProxyAccount: IAccountService {private readonly IAccountService _ accountService; / constructor takes no arguments / directly creates the AccountService class / public ProxyAccount () {_ accountService = new AccountService () in it. } public void Reg (User user) {before (); _ accountService.Reg (user); after ();} private void before () {Console.WriteLine ("Agent: logic before registration") } private void after () {Console.WriteLine ("Agent: logic after registration");}

Called in the Main method:

Using StaticDemo.Model;using StaticDemo.Services;using System;namespace StaticDemo {class Program {static void Main (string [] args) {# region decorator mode / instantiated object / / IAccountService accountService = new AccountService () / instantiate the decorator class and use the above example to pass the value / / var account = new AccountDecorator (accountService) to the constructor; / / var user = new User {Name = "Rick", Password = "12345678"}; / call the decorator class's registration method, which is equivalent to calling the instantiated object's registration method / / account.Reg (user) # endregion # region proxy mode var account = new ProxyAccount (); var user = new User {Name = "Tom", Password = "12345678"}; account.Reg (user); # endregion Console.ReadKey ();}

Running result:

Some people may find that the decorator class is very similar to the proxy class, and the function is exactly the same, except that the constructor is different. So is there any difference between decorator mode and proxy mode? Some things seem to have little difference in form, but in fact they are very different. They are indeed the same in form, whether it is a decorator class or a proxy class, they all implement the same interface, but they are different when they are used.

The decorator pattern focuses on dynamically adding methods on an object, while the proxy pattern focuses on controlling access to the object. To put it simply, using the proxy pattern, our proxy class can hide the specific information of a class. Var account = new ProxyAccount (); just look at this code without looking at the source code, and you don't know who the agent is in it.

When using the proxy pattern, we often create an instance of an object in the proxy class: _ accountService = new AccountService (). When we use the decorator pattern, we usually pass the original object as an argument to the decorator's constructor. To put it simply, when using the decorator pattern, we can know exactly who the decorator is, and more importantly, the proxy class is written dead, and the relationship is determined at compile time. The decorator is determined at run time.

2. Dynamic agent

There are also two ways to implement dynamic proxy.

The way it is woven into the code. For example, a third-party plug-in for PostSharp. We know that the .NET program will eventually be compiled into the IL intermediate language, and when compiling the program, PostSharp will dynamically modify the IL and add code to the IL, which is how the code is woven.

It is realized by reflection. There are many ways to implement it through reflection, and there are also many frameworks that implement AOP, such as Unity, MVC filters, Autofac, and so on.

Let's first look at how to use PostSharp to implement dynamic proxies. PostSharp is a third-party plug-in for a fee.

First create a new console application, and then create an order business class:

Using System;namespace PostSharpDemo {/ order business class / public class OrderBusiness {public void DoWork () {Console.WriteLine ("order execution");}

Then call in the Main method:

Using System;namespace PostSharpDemo {class Program {static void Main (string [] args) {OrderBusiness order = new OrderBusiness (); / / call method order.DoWork (); Console.ReadKey ();}

Running result:

At this time, a new requirement is put forward. To add a logging function to record the execution of the business, according to the previous method, you need to define a log helper class:

Using System;using System.IO;namespace PostSharpDemo {public class LgoHelper {public static void RecoreLog (string message) {string strPath = AppDomain.CurrentDomain.BaseDirectory+ "\\ log.txt"; using (StreamWriter sw=new StreamWriter (strPath,true)) {sw.WriteLine (message); sw.Close ();}

If we don't use AOP, we need to instantiate the Loghelper object where the log is recorded, and then log:

Using System;namespace PostSharpDemo {/ order business class / public class OrderBusiness {public void DoWork () {/ / logging LgoHelper.RecoreLog (before business execution); Console.WriteLine (order execution business); LgoHelper.RecoreLog (after business execution);}

Let's run the program again to see the results:

Let's look at the contents of the log:

This modification can achieve the function of logging. But the above method will modify the existing code, which violates the opening and closing principle. And adding logs is not a change in business requirements, and business code should not be modified. Let's use AOP to do this. First install PostSharp, search directly in NuGet, and then install:

Then define a LogAttribute class that inherits from OnMethodBoundaryAspect. This Aspect provides join point methods such as entry and exit functions. In addition, "[Serializable]" must be set on Aspect, which is related to the lifecycle management of Aspect within PostSharp:

Using PostSharp.Aspects;using System;namespace PostSharpDemo {[Serializable] [AttributeUsage (AttributeTargets.Method, AllowMultiple = false, Inherited = true)] public class LogAttribute: OnMethodBoundaryAspect {public string ActionName {get; set;} public override void OnEntry (MethodExecutionArgs eventArgs) {LgoHelper.RecoreLog (ActionName + "before business execution") } public override void OnExit (MethodExecutionArgs eventArgs) {LgoHelper.RecoreLog (ActionName + "after business execution");}

Then the Log attribute is applied to the DoWork function:

Using System;namespace PostSharpDemo {/ order business class / public class OrderBusiness {[Log (ActionName = "DoWork")] public void DoWork () {/ / log / / LgoHelper.RecoreLog ("before executing business"); Console.WriteLine ("execute order business") / / LgoHelper.RecoreLog ("after business execution");}

After this modification, you only need to add a feature to the method, and the previously logged code can be commented out, so that the business logic code will not be modified and run the program:

Look at the log:

This implements the AOP function.

We are looking at using Remoting to implement dynamic proxies.

First, create a User entity class:

Namespace DynamicProxy.Model {public class User {public string Name {get; set;} public string Password {get; set;}

Then create an interface with a registration method:

Using DynamicProxy.Model;namespace DynamicProxy.Services {public interface IAccountService {void Reg (User user);}}

Then create an implementation class for the interface:

Using DynamicProxy.Model;using System;namespace DynamicProxy.Services {public class AccountService: MarshalByRefObject, IAccountService {public void Reg (User user) {Console.WriteLine ($"{user.Name} registered successfully");}

Then create a generic dynamic proxy class:

Using System;using System.Runtime.Remoting;using System.Runtime.Remoting.Messaging;using System.Runtime.Remoting.Proxies;namespace DynamicProxy {public class DynamicProxy: RealProxy {private readonly T _ target; / / before execution public Action BeforeAction {get; set;} / / after execution public Action AfterAction {get; set } / / proxied generic class public DynamicProxy (T target): base (typeof (T)) {_ target = target;} / / proxy class calls method public override IMessage Invoke (IMessage msg) {var reqMsg = msg as IMethodCallMessage; var target = _ target as MarshalByRefObject; BeforeAction () / / this is where the method / / target in the proxy class represents the proxied object, and reqMsg represents the method to be executed var result = RemotingServices.ExecuteMessage (target, reqMsg); AfterAction (); return result;}

We see that there are two generic delegates in this generic dynamic proxy class: BeforeAction and AfterAction. The proxy generic class is passed in through the constructor. Finally, the Invoke method is called to execute the method of the proxy class.

Finally, we also create a proxy factory class that is used to create a proxy object, which is created by calling a dynamic proxy:

Using System;namespace DynamicProxy {/ dynamic proxy factory class / public static class ProxyFactory {public static T Create (Action before, Action after) {/ / instantiate the proxied generic object T instance = Activator.CreateInstance () / / instantiate dynamic proxy, create dynamic proxy object var proxy = new DynamicProxy (instance) {BeforeAction = before, AfterAction = after}; / / return transparent proxy object return (T) proxy ();}

Finally, we call in the Main method:

Using DynamicProxy.Model;using DynamicProxy.Services;using System;namespace DynamicProxy {class Program {static void Main (string [] args) {/ / call the dynamic proxy factory class to create a dynamic proxy object, pass AccountService, and pass two delegates var acount = ProxyFactory.Create (before: () = > {Console.WriteLine ("before registration") }, after: () = > {Console.WriteLine ("after registration");}); User user = new User () {Name= "Zhang San", Password= "123456"}; / / call registration method acount.Reg (user) Console.ReadKey ();}

The result of running the program:

In this way, the dynamic proxy is implemented by using Remoting.

Thank you for reading! This is the end of this article on "what is the idea of AOP programming in C#". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, you can share it for more people to see!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report