Integration with third-party ioc/di frameworks in ASP. NET core applications

Source: Internet
Author: User
Tags webhost
In an ASP. NET core application, the consolidation of the third-party DI framework can be achieved by returning a serviceprovider to the Configureservices method that defines the startup type. But it is not so easy, the following examples to share with you

First, the Configureservices method returned serviceprovider no use!

We can illustrate this problem with a simple example. We first defined the following one myserviceprovider, which is actually the encapsulation of another serviceprovider. For simplicity, we use a dictionary to store the mapping between the service interface and the implementation type, which can be registered by calling the Registe method. In the GetService method that provides the service instance, if the provided service type has already been registered, we will create and return the corresponding instance object, otherwise we will use the encapsulated serviceprovider to provide the service. To ensure that the service instance can be recycled properly, if the service type implements the IDisposable interface, we will add it to the collection represented by the field _disposables. When the Dispose method of Myserviceprovider is called, the Dispose method provided by these service instances is called.


 public class Myserviceprovider:iserviceprovider, IDisposable {private IServiceProvider _innerserviceprovider; private Dictionary<type, type> _services;  Private list<idisposable> _disposables; Public Myserviceprovider (IServiceProvider innerserviceprovider) {_innerserviceprovider = Innerserviceprovider; _services = new Dictionary<type, type> (); _disposables = new list<idisposable> (); } public Myserviceprovider Register<tfrom, tto> () where Tto:tfrom, new () {_services[typeof (tfrom)] = typeof (TTo) ; return this; public Object GetService (type ServiceType) {type implementation, if (_services. TryGetValue (servicetype, out implementation)) {Object Service = Activator.CreateInstance (Implementation); IDisposable Disposbale = service as IDisposable; if (null! = Disposbale) {_disposables. ADD (Disposbale); } return service; } return _innerserviceprovider.getservice (servicetype); } public void Dispose () {(_innerserviceprovider as IDisposable)?. DisposE (); foreach (var it in _disposables) {it. Dispose (); } _disposables. Clear (); } }

We use Myserviceprovider in an ASP. NET core application as follows. As in the following code fragment, in the registered Starup type, we let the Configureservices method return a Myserviceprovider object. The mapping between the service interface Ifoobar and the implementation type Foobar is registered on this Myserviceprovider object. When processing the request, we take advantage of the Requestservices property of the current HttpContext object to get the serviceprovider to service the request processing and try to use it to get the registered Ifoobar service.


public class Program {public static void Main (string[] args) {new Webhostbuilder (). Usekestrel (). Usestartup<startup> (). Build (). Run (); }} public  class Startup {public IServiceProvider configureservices (iservicecollection services) {return new Myservi Ceprovider (services. Buildserviceprovider ()). Register<ifoobar, foobar> (); } public  void Configure (Iapplicationbuilder app) {app. Usedeveloperexceptionpage (). Run (Async context = await context. Response.writeasync (context. Requestservices.getrequiredservice<ifoobar> (). GetType (). Name)); }} public interface Ifoobar {} public class Foobar:ifoobar {}

The whole application is as simple as it seems to be, but when we launch the app and access the app using the browser, we'll see an error like the one below. The error message indicates that the service interface Ifoobar has not been registered.

Second, why?

We clearly registered the mapping between Ifoobar and Foobar in the returned serviceprovider, why did Requestservices return serviceprovider say that the service has not yet been registered? The only explanation is that the serviceprovider returned by the Configureservices method is not the same serviceprovider as HttpContext requestservices. In fact, they are not the same object.

The serviceprovider returned by the Configureservices method will be the serviceprovider of the webhost, for each request received, Webhost will create a new serviceprovider based on this serviceprovider as the requestservices attribute of the HttpContext, two serviceprovider with parent-child management. As usual, if the serviceprovider returned by Requestservices is created based on the serviceprovider returned by the Configureservices method, it should also be able to recognize the registered service type Ifoobar, So why is there still a mistake?

To understand this problem, you need to know how this so-called "sub-serviceprovider" is created, which involves the concept of servicescope. Simply put, Servicescope is a serviceprovider package that determines the life cycle of the latter. Servicescope is created by Servicescopefactory, which is registered as a service on "parent serviceprovider". When "parent serviceprovider" needs to create "sub-serviceprovider", It calls the GetService method to get the Servicescopefactory object (the service interface used is iservicescopefactory) and uses the latter to create a servicescope, The serviceprovider provided by this servicescope is the "child serviceprovider" that is returned.

But for our Myserviceprovider object, when the GetService method that calls it tries to get the Servicescopefactory object, Obtained is actually the encapsulated Serivceprovider associated servicescopefactory, then naturally created "sub serviceprovider" also has nothing to do with Myserviceprovider.

Third, how to solve this problem?

Now that we know the root of the problem, we naturally have a solution. The solution is not complicated, we only need the Myserviceprovider GetService method to return the servicescopefactory that reflects its own service registration. For this we define the following servicescope and corresponding servicescopefactory.


Internal class Servicescope:iservicescope {private Myserviceprovider _serviceprovider;  Public Servicescope (Iservicescope innserservicescope, Dictionary<type, type> services) {_serviceprovider = new Myserviceprovider (Innserservicescope.serviceprovider, services); } public IServiceProvider ServiceProvider {get {return _serviceprovider;}}  public void Dispose () {_serviceprovider.dispose ();}}  Internal class Servicescopefactory:iservicescopefactory {private iservicescopefactory _innerservicefactory; private Dictionary<type, type> _services;  Public Servicescopefactory (Iservicescopefactory innerservicefactory, Dictionary<type, Type> services) {_ Innerservicefactory = innerservicefactory; _services = Services; } public Iservicescope Createscope () {return new Servicescope (_innerservicefactory.createscope (), _services);}}

In addition to this, we have added a constructor for Myserviceprovider, and the GetService method adds the corresponding code for iservicescopefactory.


public class Myserviceprovider:iserviceprovider, idisposable{public Myserviceprovider (IServiceProvider Innerserviceprovider, Dictionary<type, type> services) {_innerserviceprovider = Innerserviceprovider; _services = Services; _disposables = new list<idisposable> (); } Public  Object GetService (Type servicetype) {if (servicetype = = typeof (Iservicescopefactory)) { Iservicescopefactory innerservicescopefactory = _innerserviceprovider.getrequiredservice<iservicescopefactory > (); return new Servicescopefactory (Innerservicescopefactory, _services); } ...  } ... }

Above share, hope to be able to solve such problems of friends help!

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.