Registering middleware classes with the Usemiddleware extension method

Source: Internet
Author: User
Tags call back

Registering middleware classes with the Usemiddleware extension method. NET core middleware registration and pipeline construction (2)----registering middleware classes with the Usemiddleware extension method Why introduce an extension method

Some middleware functions are relatively simple, others are more complex, and depend on other components. In addition to registering the middleware directly with the Applicationbuilder use () method, you can also register the middleware with the Applicationbuilder extension method Usemiddleware (). In this case, the type can be registered, and the method will parse the type by reflection and wrap it into func<reuqestdelegate,requestdelegate> and then call the use () method to register.

In this case, it is generally intuitive to write a middleware by inheriting an abstract class and implementing one of the methods. But that's not what the. NET core does. Middleware classes use conventions rather than inheritance to constrain them. The convention here is to agree to the original meaning, such as the agreed to the middleware class must contain a method called Invoke, called other can not, there is no overload. Because the middleware class does not have any inheritance constraints, the registration process is to look for a method named Invoke by reflection, and then wrap it into requestdelegate. This article is about to write a middleware class what are the conventions and middleware class registration.

0x01 one of the simplest examples

Let's look at the simplest example of a middleware class:

As I said in the previous article, the middleware essence is a method that takes a HttpContext parameter and returns a task. In the above middleware class, Invoke is the method. In order to be able to invoke the next middleware, the current middleware also needs to save a reference to the next middleware. This reference is passed through the constructor function, and if the current middleware does not need to call back the middleware, the reference can be completely saved. If you want to register this middleware, we can do this:

But if our middleware is more complex and relies on many other modules, then we need to construct an instance of the dependent module when registering, and pass these dependencies in the constructor of the middleware class. This strengthens the coupling between the middleware and the dependent modules. In order to reduce this coupling and to enjoy the convenience of dependency injection, a usemiddleware<t> extension method is provided to register the middleware class T.

The Usemiddleware extension method finds the Invoke method in the middleware class above, creates an instance of the above class, encounters the type that needs to be injected when creating the instance, and then wraps the Invoke method as reuqestdelegate, wrapping it as a func< Requestdelegate,requestdelegate>, and then registered to Ilist<func<requestdelegaet by Applicatonbuilder's use method, which was mentioned in the previous article, The requestdelegate>.

From the above simplemiddleware we can see that this class does not have any inherited relationships, so what are the constraints we need to be aware of when writing a middleware class? We just have to look at the process of Usemiddleware registration middleware. The following is an analysis of the Usemiddleware () method, which is not interested in code analysis and can skip directly to the following conclusions and tests.

The process of registering a middleware class with the 0x02 extension method

The use of the usemiddleware<t> extension method to register the middleware class T mainly consists of the following key steps:

1. Find the Invoke method for the middleware class. The Usemiddleware method obtains a list of all public and non-static methods of the registered middleware class through reflection, then finds the method named Invoke from which the Invoke method is not overloaded, confirms that the Invoke method returns a task, Confirm that the first parameter of the Invoke method is HttpContext, and the last two checks are to wrap the Invoke method as Requestdelegate.

2. Select the best constructor. Insert the next middleware reference next into the list of arguments passed from Usemiddleware to the first, as a given argument list.

Then get all the constructors of the middleware class, take the parameters in order from the given argument list, type match the parameters of the constructor, and select the best constructor for the constructor that matches the most. Match the same code in the preceding constructor (which omits many details that match the best constructor, which is interesting to see the code yourself).

It is important to note that if there is a parameter p in the given argument list and no matching type is found in the current constructor argument list, then this constructor cannot be the best constructor. This means that the parameter list of the selected best constructor must be a superset of the given argument list. Just now, the next middleware next is inserted into the first of the given parameter list, so the best constructor parameter selected must contain the parameter requestdelegate. If all constructors do not contain requestdelegate, an exception is thrown.

3. Construct an instance of the middleware class. Once the best constructor has been found, the constructor is then used to construct an instance of the middleware class. For all parameters in the constructor, you can find the type match from the given list of arguments and get the parameters from the given argument list. Cannot be found from the parameter list, the attempt is taken from the dependency injection container, the check that is not found in the dependency injection container is not a default value, and the default value does not throw an exception.

4. Once the instance is constructed, if the Invoke method has only one parameter (HttpContext), the Invoke method of the instance is wrapped as requestdelegate, which is then packaged as Func<requestdelegate, Requestdelegate> is then registered using the use method. If there are multiple parameters that do not conform to the requestdelegate constraint, invoke is wrapped two times to conform to Requestdelegate. The dependency in the Invoke parameter is attempted from the dependency injection container in the two-time wrapper.

0X03 some conclusions

The following summarizes some of the middleware class conventions, mainly based on the understanding of the code, there are errors or incomplete place please correct me.

Middleware-related methods:

1. The middleware method must be called invoke, and is public, non-static.

The first parameter of the 2.Invoke method must be a HttpContext type.

The 3.Invoke method must return a task.

The 4.Invoke method can have more than one parameter, except for HttpContext, which attempts to get from the dependency injection container.

5.Invoke methods cannot have overloads.

About constructors:

1. The constructor must contain the Requestdelegate parameter, which is passed to the next middleware.

2. The Requestdelegate parameter in the constructor parameter does not have to be placed first, and can be anywhere.

3. The constructor can have multiple parameters, the parameter will take precedence from the given argument list, followed by the dependency injection container, and the failure will attempt to get the default value, both failures will throw an exception.

4. Constructors can have more than one, by which time the highest match is chosen based on the constructor parameter list and the given argument list.

Personal advice, really just a few personal suggestions:

1. Except for special cases, only one constructor is reserved to eliminate redundant constructor matching checks.

2. Inject the required dependencies in the constructor instead of invoke.

3. With regard to the order of the constructor parameters, place the requestdelegate first, followed by the parameters given in the Usemiddleware method, and the parameter order in the constructor and the order in the given argument list are the best, and then the arguments that need to be injected, and finally the parameters with the default values. All of the above except that the default parameter must be placed in the last order is not required, but in the order of the above will be clearer, and can make the cost of the instance creation is minimal.

The 4.Invoke method retains only one HttpContext parameter. This saves you from wrapping the Invoke method two times.

5. Further expand the applicationbuilder to create more semantically explicit alternatives to use/usemiddleware, such as USEMVC, Usestaticfiles.

What I can think of in 1, and the special case, is to give Usemiddleware a different list of arguments, and then match to different constructors to create the instance. Specific usage scenarios were not thought of.

0x04 test

In the previous article we wrote about a time-consuming middleware that records all the middleware behind it. It was registered directly with the use method. Now let's write it as a middleware class, and write the timing function as a stopwatch class and add it to the dependency injection container.

The following is the code for the Timer class:

Here is the code for the middleware class

Here is the addition of stopwatch to the dependency injection container

Here's how to add Timemiddleware middleware code using the Usemiddleware extension method

Of course, you can also not add stopwatch to the dependency injection container, but instead give the parameters directly in the Usermiddleware method.

If stopwatch is added to the dependency injection container and stopwatch is provided when Usemiddleware is registered, the stopwatch that is provided at the time of the parameter matching order is eventually used.

Run to see the same effect as the previous article.

0x05 written in the last

The Usemiddleware method makes it easy to register middleware, and colleagues reduce the coupling between middleware and other dependent modules. However, regardless of the extension method, the end is to implement the middleware registration through the use method. The next article will write about other extension methods for registering middleware, map, Mapwhen, and run.

Category:. NET Core, ASP.

Registering middleware classes with the Usemiddleware extension method

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.