preface
In fact, many projects have the concept of Aop for data interception and data caching, but the implementation methods are different; Before, everyone may use filters to realize the function of Aop. If it is ASP NETCORE may also use middleware; This implementation method is to intercept during the request process. If we want to cut across in the service layer, that method is obviously difficult to use, and we need to use "real Aop".
Start directly
In fact, what we often call "real Aop" is actually a dynamic agent. I don't record the theoretical knowledge here, and I can't write it well. Let's find Du Niang by ourselves. Let's go directly to the code:
Build a console project normally, and the directory structure is as follows:
Here is a simple user maintenance simulation. The code is as follows:
Define Model
1 2 3 4 5 public class User { public string Name { get; set; } public int Age { get; set; } }
Define interface
1 2 3 4 public interface IUserService { bool AddUser(User user); }
Implementation interface
1 2 3 4 5 6 7 8 public class UserService : IUserService { public bool AddUser(User user) { Console.WriteLine("User added successfully"); return true; } }
main method
1 2 3 4 5 6 7 8 9 10 11 class Program { static void Main(string[] args) { User user = new User {Name="Zoe", Age=18 }; IUserService userService = new UserService(); userService.AddUser(user); //Console.ReadLine(); } }
The project is very simple, just run normally;
If we want to do something else before and after the increase of users, what should we do?
Solution:
1. Directly modify the service layer code and deal with relevant businesses before and after storage;
2. Use Aop without modifying the original method.
We won't talk about scheme 1. Everyone must know that the function can be realized, but the original code is required. How to deal with similar things when adding many interfaces? If it is added, what will happen if some functions are not needed in the next version? Obviously, it's not very flexible, and if you change it repeatedly, there's a great chance of a Bug!!!
Direct dynamic proxy:
1. Add a class for business operations;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 using System; using System.Collections.Generic; using System.Reflection; using System.Text; namespace Aop { public class MyDecorator : DispatchProxy { //Specific type public object TargetClass { get; set; } protected override object Invoke(MethodInfo targetMethod, object[] args) { Console.WriteLine("Execute business before adding users"); //Call the original method targetMethod.Invoke(TargetClass, args); Console.WriteLine("Execute business after adding users"); return true; } } }
Optimize the code of Main() function
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Program { static void Main(string[] args) { User user = new User {Name="Zoe", Age=18 }; IUserService userService = new UserService(); userService.AddUser(user); //Dynamic agent //1. Create proxy object IUserService userService1 = DispatchProxy.Create<IUserService, MyDecorator>(); //2. Because the instance method is called, the specific type needs to be passed ((MyDecorator)userService1).TargetClass = new UserService(); userService1.AddUser(user); Console.ReadLine(); } }
Look at the dynamic agent part, so as to uniformly realize the Aop programming of user maintenance service layer. Look at the operation results:
Is this more flexible? You don't need to deal with it in one business layer, and the choice is very simple. Don't just don't apply this kind of business.
Reference to third-party libraries
It's a little troublesome to use the native method. What else is there, such as forced conversion, type transfer, castle Core will help us do everything well. Next, let's see how to use it.
1. First, castle Core;
2. Add interceptor class and expand business;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 using Castle.DynamicProxy; using System; using System.Collections.Generic; using System.Text; namespace Aop { class MyIntercept : IInterceptor { public void Intercept(IInvocation invocation) { //Before executing the original method Console.WriteLine("Execute business before adding users"); //Execute the original method invocation.Proceed(); //After executing the original method Console.WriteLine("Execute business after adding users"); } } }
3. The main function adds castle Core usage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 using AopModel; using AopService; using Castle.DynamicProxy; using System; using System.Reflection; using System.Reflection.Metadata; namespace Aop { class Program { static void Main(string[] args) { User user = new User {Name="Zoe", Age=18 }; IUserService userService = new UserService(); userService.AddUser(user); Console.WriteLine("=============Dynamic agent=============="); //Dynamic agent //1. Create proxy object IUserService userService1 = DispatchProxy.Create<IUserService, MyDecorator>(); //2. Because the instance method is called, the specific type needs to be passed ((MyDecorator)userService1).TargetClass = new UserService(); userService1.AddUser(user); Console.WriteLine("=============Castle.Core=============="); ProxyGenerator generator = new ProxyGenerator(); var u = generator.CreateInterfaceProxyWithTarget<IUserService>(new UserService(),new MyIntercept()); u.AddUser(user); Console.ReadLine(); } } }
That's it. Look at the running results:
To sum up, the third party is relatively simple to use and encapsulates many methods, not only the above methods. The following example integrates Autofac and castle Core in ASP The application in NETCORE (using Asp.NetCore project, because many real projects are API or Web projects, so it is more practical) only provides you with ideas. As follows:
1. First, we create an ASP NETCORE project. Here I create an API project, which can run normally. The project structure is as follows;
2. Three packages are introduced and installed through Nuget, starting with Autofac, as follows
Note: Autofac Extras. Dynamicproxy is an AOP related component, including castle Core, so you don't need to install Castle separately Core.
3. Simulate the preparation of user maintenance related logic, and the code is as follows:
Interface:
1 2 3 4 public interface IUserService { int AddUser(string strName, int nAge); }
Implementation:
1 2 3 4 5 6 7 8 9 10 11 public class UserService : IUserService { /// <summary> ///Simulate new users. There is no data processing layer written here /// </summary> public int AddUser(string strName, int nAge) { Console.WriteLine("Add user to database"); return 1; } }
4. Write interceptor logic, i.e. agent:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 using Castle.DynamicProxy; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace WebAop.Aop { public class UserAop : IInterceptor { //The key is to carry out relevant logic processing before and after the implementation of the method public void Intercept(IInvocation invocation) { Console.WriteLine("Perform other processing before adding a user"); //Call the original method invocation.Proceed(); Console.WriteLine("Perform other processing after adding a user"); } } }
5. Integrate Autofac to register the user maintenance service into the container:
- First, add methods in Startup as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public void ConfigureContainer(ContainerBuilder builder) { //Registered user maintenance business layer var basePath = AppContext.BaseDirectory; var serviceDll = Path.Combine(basePath, "AopService.dll"); if(!File.Exists(serviceDll)) { throw new Exception("Assembly not found"); } //Register AOP interceptor builder.RegisterType(typeof(UserAop)); builder.RegisterAssemblyTypes(Assembly.LoadFrom(serviceDll)) .AsImplementedInterfaces() .EnableInterfaceInterceptors()//To open the section, you need to introduce Autofac Extras. DynamicProxy .InterceptedBy(typeof(UserAop));//Specify interceptors. You can specify multiple interceptors }
- Then add the factory of Autofac in the program, as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Autofac.Extensions.DependencyInjection; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace WebAop { public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) //Need to introduce Autofac Extensions. Dependencyinjection is important here, otherwise Autofac won't work .UseServiceProviderFactory(new AutofacServiceProviderFactory()) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); } }
6. Add the UserController method as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using AopService.Interface; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace WebAop.Controllers { [Route("api/[controller]")] [ApiController] public class UserController : ControllerBase { private IUserService _userService; <strong> //It has been registered through Autofac, and can be injected directly through the constructor public UserController(IUserService userService) { _userService = userService; }</strong> [HttpGet] [Route("AddUser")] public IActionResult AddUser(string name,int age) { <strong> //Call the user's new operation normally _userService.AddUser(name, age);</strong> return Ok("Success!!"); } } }
7. When the operation starts, in order to see the console print conveniently, the operation is carried out in the mode of project startup. The results are as follows:
Enter directly in the browser http://localhost:5000/api/User/AddUser?name=sss&age=12 , then enter, and then look at the console print:
Summary:
AOP is very useful in pre-processing or post-processing of some businesses. It can be used flexibly without modifying the original code logic. It is much better than modifying the original code maintenance!!!
Turn https://www.cnblogs.com/zoe-zyq/p/12803450.html