Dora. Interception, an AOP framework for. NET Core: Different Interceptor definition methods,

Source: Internet
Author: User

Dora. Interception, an AOP framework for. NET Core: Different Interceptor definition methods,

Compared with other mainstream AOP frameworks in the Community, Dora. Interception provides completely different programming methods in Interceptor. We have not defined an interface for Interceptor. It is precisely because we do not need to implement a predefined interface that the Interceptor definition in Dora. Interception becomes more free. In addition, the asynchronous execution of Interceptor is designed by Dora. interception is most concerned at the beginning. That is to say, if the target method of the Interceptor application is asynchronous, Interceptor itself should also be granted the asynchronous execution capability. Next, let's talk about how to define your Interceptor if you use Dora. Interception.

Directory
One or two proxy generation methods
2. InterceptorDelegate
Iii. Define the Interceptor type
Iv. Method Injection

One or two proxy generation methods

Dora. Interception uses the dynamic generation of proxy types (using IL Emit) to intercept the target method. Specifically, we provide two types of proxy types:

  • If an interface is implemented for the target type, the generated proxy type is used to implement this interface. The interface methods implemented in the proxy type are intercepted, this means that all methods defined in the interface can be intercepted. The proxy object encapsulates the target object. If you need to call the target method, the corresponding method of the target object will be called. We will generate this form of proxy type as "interface-based code generation ".
  • If the target type does not implement the interface, the generated proxy type is directly derived from this type. If a virtual method defined in the base class needs to be blocked, we will rewrite this method in the proxy class to perform interception operations. You can call the method corresponding to the base class to call the target method. We will generate this form of proxy type as "virtual method-based code generation ".
2. InterceptorDelegate

The core of AOP is to define some non-business functions as corresponding Interceptor and inject them into the calling process of the target method in the form of Crosscutting. In other words, Interceptor needs to intercept the execution of the target method and execute the injected operation in the context of the current method. If we define the context of the method execution as an InvocationContext, Interceptor's interception operation can be expressed as an Action <InvocationContext>. However, as we have mentioned above, an Interceptor should be granted the asynchronous execution capability. According to the Task-based parallel programming mode, Interceptor's own interception operations should be represented as a Func <InvocationContext, task>.

In Dora. Interception, we define the following abstract InvocationContext to indicate the context of method execution to be intercepted. Its Method and TargetMethod return represent the MethodBase object of the current Method. If an interface-based proxy type is used, the former indicates the Method defined on the interface, the latter indicates the method defined on the target type. If the proxy type generation method is based on the virtual method, the two attributes return the same object, indicating the method defined in the intercepted type. Proxy and Target indicate the current Proxy object and the encapsulated Target object respectively. If the Proxy type generation method based on the virtual method is adopted, the two attributes return the same object.

  1 public abstract class InvocationContext  2 {  3     public abstract MethodBase Method { get; }  4     public MethodBase TargetMethod { get; }  5     public abstract object Proxy { get; }  6     public abstract object Target { get; }  7     public abstract object[] Arguments { get; }  8     public abstract object ReturnValue { get; set; }  9 }

Arguments of InvocationContext indicates the parameters called by the current method, including both common input parameters and ref/out parameters. It is worth mentioning that the Arguments attribute is readable and writable, that is, Interceptor can modify the value of an element in this attribute to modify a parameter value. Since the entire call process shares the same InvocationContext object, any modifications made by an Interceptor to Arguments will affect the subsequent execution of Intercecptor and the final target method. The ReturnValue of InvocationContext indicates the return value of the method call. If the target method is finally called, its return value is eventually reflected in this attribute. This attribute is readable and writable. Any Interceptor can modify this attribute to change the return value of the method call.

Because the execution context of the current method call is represented as an InvocationContext object, blocking operations on Interceptor can be represented as a Func <InvocationContext, Task> type delegate. However, for programming convenience, we have defined the corresponding delegate type InterceptDelegate as follows. Since multiple interceptors can be applied to a method at the same time, after an Interceptor completes its own defined interception operation, it will decide whether to continue calling the subsequent Interceptor or target method, in other words, subsequent calls to Interceptor or target methods are also part of the current interception operation. Therefore, we define another delegate type InterceptorDelegate to represent an Interceptor object.

  1 public delegate Task InterceptDelegate(InvocationContext context);  2 public delegate InterceptDelegate InterceptorDelegate(InterceptDelegate next);

For InterceptorDelegate delegation indicating Interceptor, its input and output are both InterceptDelegate delegation. Interceptor calls Interceptor or the target method in the future through InterceptDelegate delegation as the input, the InterceptDelegate delegate object returned by it reflects the implemented interception operation. In this sense, an InterceptorDelegate delegate not only represents a single Interceptor object, but also represents an Interceptor Chain composed of one more Interceptor. From another perspective, an Interceptor itself represents an Interceptor Chain because an Interceptor has been implemented for subsequent Interceptor execution.

Iii. Define the Interceptor type

Although Dora. interception always uses an InterceptorDelegate delegate at the underlying layer to represent Interceptor (Chain). For programming convenience, we still define Interceptor as a type, the Interceptor type we define only needs to adopt the following "Conventions:

  • The Interceptor type does not need to implement any interfaces. We only need to define a common public instance type.
  • The Interceptor type must have a public constructor, and the first parameter of the constructor must be InterceptDelegate, which is used to call subsequent Interceptor or target methods.
  • In addition to the first parameter, the preceding constructor can contain any Parameter definition.
  • The interception function is implemented in the agreed InvokeAsync method. This is an asynchronous method whose return type is Task. Its first parameter type is InvocationContext.
  • In addition to parameters that indicate the current execution context, InvokeAsync can contain any Parameter definition, but these parameters must be provided in DI mode.
  • Whether the current Interceptor calls the subsequent Interceptor or target method depends on whether you call the InterceptDelegate delegate object passed in by the constructor.

Next, we will briefly introduce how to define our Interceptor type by following the above conventions through the example. As shown in the following code snippet, FoobarInterceptor, as an Interceptor type, has a common instance constructor. As the first mandatory parameter, next indicates the InterceptDelegate delegate object used to call subsequent Interceptor or target methods. In addition to this parameter, we also define two additional interface parameters, which are saved to the corresponding field or attribute. The interception operation is defined in the InvokeAsync method. The method name (InvokeAsync), the return type (Task), and the type of the first parameter (InvocationContext) are all part of our agreement. In this method, we output the Foo and Bar attributes, and finally pass back the call using the InterceptDelegate delegate object specified by the constructor.

  1 public class FoobarInterceptor  2 {  3     public IFoo Foo { get; }  4     public IBar Bar { get; }  5     private InterceptDelegate _next;  6     public FoobarInterceptor(InterceptDelegate next, IFoo foo, IBar bar)  7     {  8         _next = next;  9         this.Foo = foo; 10         this.Bar = bar; 11     } 12  13     public Task InvokeAsync(InvocationContext context) 14     { 15         Console.WriteLine(this.Foo); 16         Console.WriteLine(this.Bar); 17         return _next(context); 18     } 19 } 20  21  22 public class FoobarAttribute : InterceptorAttribute 23 { 24     public override void Use(IInterceptorChainBuilder builder) 25     { 26         builder.Use<FoobarInterceptor>(this.Order); 27     } 28 } 29  30 public interface IFoo { } 31 public interface IBar { } 32 public class Foo : IFoo { } 33 public class Bar : IBar { }

FoobarAttribute is a feature used to register FoobarInterceptor. FoobarAttribute is derived from the abstract base class InterceptorAttribute. We will introduce InterceptorAttribute and related Interceptor registration types in subsequent articles. Dora. A notable feature of Interception is.. NET Core's DI implements seamless integration. Specifically, any service required in Interceptor can be provided directly in DI mode. For example, the Foo of FoobarInterceptor and the service instance corresponding to the Bar attribute. As shown in the following code snippet, we label FoobarAttribute to the virtual method Invoke of the Demo type. In the Main method, we add the Service Registration corresponding to IFoo, IBar, and Demo to the created ServiceCollection, and then call the BuildInterceptableServiceProvider method of the latter to create a ServiceProvider with the "intercept" feature. If the service type provided by this ServiceProvider can be intercepted, it dynamically generates the corresponding proxy type using the corresponding proxy type generation mechanism, and finally creates the corresponding proxy instance.

  1 class Program  2 {  3     static void Main()  4     {  5         var demo = new ServiceCollection()  6             .AddScoped<IFoo, Foo>()  7             .AddScoped<IBar, Bar>()  8             .AddScoped<Demo, Demo>()  9             .BuildInterceptableServiceProvider() 10             .GetRequiredService<Demo>(); 11         demo.Invoke(); 12     } 13 } 14  15 public class Demo 16 { 17     [Foobar] 18     public virtual void Invoke() 19     { 20         Console.WriteLine("Demo.Invoke() is invoked"); 21     } 22 }

Executing the above Code will generate the following output results on the console. We can see that the application is in Domo. the FoobarInteceptor on the Invoke method is executed normally, and the two service types Foo and Bar it depends on are exactly the same as the service registration.

1 public class FoobarInterceptor 2 {3 private InterceptDelegate _ next; 4 public FoobarInterceptor (InterceptDelegate next) 5 {6 _ next = next; 7} 8 9 public Task InvokeAsync (InvocationContext context, IFoo foo, IBar bar) 10 {11 Console. writeLine (foo); 12 Console. writeLine (bar); 13 return _ next (context); 14} 15}


Dora. Interception: an all-new version of the AOP framework for. NET Core
Dora. Interception, an AOP framework built for. NET Core: Different Interceptor definition methods

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.