Objective
In the previous article, I briefly discussed some basic knowledge, such as the use of ASP. NET Core Middleware, the simple use of Di and the use of embedded resources. This article is a combination of basic knowledge to build a basic framework.
So what's the function of the framework?
- Intercept Layim Requests
- Simple routing Features
- Routing Scheduler
- Universal interface
Based on the above four points to build the foundation framework. Other caches, logs, etc. are not introduced first.
Intercept Layim Requests
As described in the previous article, implement a middleware can do interception request operation, in other words, if it is Layim request, we do not let go. If not, then goodbye. However, since we have used the system's Embeddedfileprovider , the static resources are given to the system to deal with the good. Here I am using a very simple way to determine whether a Layim request is to be judged by the path prefix of the request. In the layimmiddleware entry method Invoke, the islayimrequest extension method is used to determine whether a Layim request is being requested. The code is as follows:
/// <summary> ///whether the Layim interface request/// </summary> /// <param name= "context" ></param> /// <param name= "Options" ></param> /// <returns></returns> Public Static BOOLIslayimrequest ( ThisHttpContext context, layimoptions options) { returnIsconfigpath (context. Request.Path.Value) | |context. Request.Path.Value.StartsWith (options. Apiprefix, stringcomparison.currentcultureignorecase); }
Yes, it was so simple and rude, it used a Startwith method. The code Isconfigpath later in the lecture. Here, the prefix can be user-definable. You can pass in the definition method in Uselayim:
App. Uselayim (options = { "/mylayim"; });
For example, in the above I changed to the beginning of /mylayim , test a bit.
Can be seen, normal processing.
Simple routing Features
Just as the path /mylayim/init?uid=1 above is how to deal with it? This is where our route is coming in. This code was also used in the code of Hangfire to implement. Its routing is simple, it is to match through regular. But the route I implemented here is not so powerful, for convenience, many URLs are defined dead. It does not support the case with parameter parsing in the URL, such as Init/{uid}. But this later will be considered. The route matching code is as follows:
/// <summary> ///find the corresponding dispatcher through path/// </summary> /// <param name= "path" ></param> /// <returns></returns> PrivateTuple<ilayimdispatcher, Match> Finddispatchermatch (stringpath) { if(string. IsNullOrEmpty (path)) {path="/"; } foreach(varDispatcherinchdispatchers) { varPattern = $"^{dispatcher. item1}$" ; varMatch = Regex.match (path, pattern, Regexoptions.cultureinvariant | Regexoptions.ignorecase |regexoptions.singleline); if(match. Success) {return NewTuple<ilayimdispatcher, match>(dispatcher. ITEM2, Match); } } return NULL; }
Yes, it's a simple way to implement routing. (The complex has not yet been studied ....) From the code we can see that the method returns a Tuple<ilayimdispatcher, match>, where is this ilayimdispatcher sacred? Let's go to the next section.
Routing Scheduler (Ilayimdispatcher)
This scheduler is not very accurate translation, but everyone understand. If you don't understand it, look at the figure below.
Interface Ilayimdispatcher There's just one way.
Task Dispatch (HttpContext context);
Then they can be subdivided into a variety of types, in the concept of CQRS , we are the aggregation of additions and deletionsbelong to the command, then we can define a commanddispatcher, But I am not so strict in accordance with the CQRS way, so query I also classify him as a query command:querycommanddispatcher.
Let's take a look at the specific code:
internal class Querycommanddispatcher<tresult>: Commanddispatcher<tresult> { Span style= "COLOR: #0000ff" >protected override string Allowmethod => HttpGet; private readonly func< HttpContext, Tresult> executefunction; public querycommanddispatcher (Func ExecuteFunction) { this . Executefuncti On = executefunction; }
Inside the constructor we pass in a func then this Func is our business logic.
For example, in routing, we add/layim/init querycommanddispatcher. the code is as follows:
// Layim initializing interfaces Routes. addquerycommand<Object> ("/init", context = { // here is just demo (logic not implemented) return context. request.query["uid"]; });
Where Addquerycommand is an extension method for routing:
/// <summary> ///registering a command route with a return value of type TResult/// </summary> /// <typeparam name= "TResult" >return type</typeparam> /// <param name= "routes" >The current road has a collection</param> /// <param name= "path" >Path</param> /// <param name= "command" >Execute Command</param> Public Static voidAddquerycommand<tresult> ( ThisRoutescollection routes,stringPath, Funccommand) {error.throwifnull (path, nameof (path)); Error.throwifnull (Command, nameof (command)); Routes. ADD (Path,NewQuerycommanddispatcher<tresult>(command)); }
Then, in this case, the first step of the route is to find the scheduler relative to /layim/init , then execute the Dispatch method, and finally return the required data. As in the first section of the final processing effect.
Universal interface The general interface is actually mentioned in the previous article, and his role is decoupling the business and the framework. That is, I designed good one universal interface, if the user does not want to use the framework's default implementation, you can define the implementation method, and then through the form of dependency injection to replace the framework default implementation, here is not repeating. For example, the default implementation of the framework is Dapper, then users can change themselves to EntityFramework or other implementations.
SummarizeThis paper simply introduces the structure and basic implementation of the framework, the implementation is relatively simple, the function is comparatively single, but because it is biased to layim business , so do not want to design how complex, how powerful, and the main capacity is not enough, haha haha.
Blog trailer:Layim.aspnetcore middleware Development Diary (four) the protagonist debut (Layim introduction)
Project Address:Https://github.com/fanpan26/LayIM.AspNetCore (This code corresponds to BLOG3 branch or direct view master) welcome the small Partners Star onlookers comments.
Layim.aspnetcore Middleware Development Diary (iii) basic framework construction