Analyzes the DependencyResolver component of ASP. net mvc,

Source: Internet
Author: User

Analyzes the DependencyResolver component of ASP. net mvc,

I. Preface

DependencyResolver is an important component in MVC. It can be seen from its name that it is responsible for parsing dependent objects. It can be said that it is an IOC container used inside the MVC framework. Many objects in MVC are created through it. Maybe we do not use it directly at ordinary times, but if you are using unity, autofac, or looking at some open-source projects, you will always see it. Next let's take a look at how this component works.

2. Understanding the working process of DependencyResolver through Controller Activation

Here, I would like to add an external question. I often have an interview: What are the core objects of asp.net? Most people will answer: Server, Request, Response, Session, Cookie. However, my answer will be HttpApplication, HttpHandler, and HttpModule. This is the core type in the pipeline model. The processing process and scalability of the entire asp.net are also based on these objects.

Back to the topic, asp.net requests are all sent to HttpHandler for processing. For MVC, the request is sent to MvcHandler, which is responsible for activating the Controller. If you do not know why, please refer to here. Here we can directly find the MvcHandler PR method:

Protected internal virtual IAsyncResult BeginProcessRequest (HttpContextBase httpContext, AsyncCallback callback, object state) {IController controller; IControllerFactory factory; ProcessRequestInit (httpContext, out controller, out factory ); // other operations // call controller. execute method} private void ProcessRequestInit (HttpContextBase httpContext, out IController controller, out IControllerFactory) {HttpContext currentContext = HttpContext. current; // obtain the controller name from the route string controllerName = RequestContext. routeData. getRequiredString ("controller"); // use ControllerBuilder to obtain ControllerFactory. The default value is DefaultControllerFactory = ControllerBuilder. getControllerFactory (); // get Controller object controller = factory through ControllerFactory. createController (RequestContext, controllerName );}

The ControllerFactory named ControllerFactory is used to create a Controller. We can also implement IControllerFactory on our own to participate in the Controller activation process. Specifically, the ControllerBuilder. Current. SetControllerFactory method is called globally. Here we mainly focus on the Controller activation process. In fact, their creation process is similar. The default ControllerFactory is DefaultControllerFactory. The CreateController method of DefaultControllerFactory is as follows:

Public virtual IController CreateController (RequestContext requestContext, string controllerName) {// obtain the Controller Type controllerType = GetControllerType (requestContext, controllerName); IController controller = GetControllerInstance (requestContext, controllerType ); return controller;} protected internal virtual IController GetControllerInstance (RequestContext requestContext, Type controllerType) {return ControllerActivator. create (requestContext, controllerType );}


As you can see, it creates an IController object through a ControllerActivator. The default value is DefaultControllerActivator. Like ControllerFactory, we can implement IControllerActivator to participate in the Controller activation process. Specifically, ControllerActivator is used as the DefaultConrtollerFactory constructor parameter, and then the ControllerBuilder. Current. SetControllerFactory method is called globally. We can see that the Controller activation process of MVC is flexible, and it provides multiple ways for us to customize the activation process. DefaultControllerActivator is defined as follows:

private class DefaultControllerActivator : IControllerActivator{  private Func<IDependencyResolver> _resolverThunk;   public DefaultControllerActivator()    : this(null)  {  }   public DefaultControllerActivator(IDependencyResolver resolver)  {    if (resolver == null)    {      _resolverThunk = () => DependencyResolver.Current;    }    else    {      _resolverThunk = () => resolver;    }  }   public IController Create(RequestContext requestContext, Type controllerType)  {    try    {      return (IController)(_resolverThunk().GetService(controllerType) ?? Activator.CreateInstance(controllerType));    }    catch (Exception ex)    {    }  }}


Here, the _ resolverThunk is a delegate used to obtain the IDepencyResolver object. The actual result is DependencyResolver. Current. We can also implement IDependencyResolver on our own to participate in the Controller activation process. Specifically, we call the static SetResolver method of DependencyResolver globally. Note that the DependencyResolver type here (this is the type, and DependencyResolver mentioned elsewhere is the component) does not implement the IDependencyResolver interface, I think it is more appropriate to name it DependencyResolverContainer. The IDepdencyResolver interface is defined as follows:

public interface IDependencyResolver{  object GetService(Type serviceType);  IEnumerable<object> GetServices(Type serviceType);}

The default DependencyResolver. Current uses the DefaultDependencyResolver type. Here it is the same as the design of ControllerFactory and ControllerActivator. If it is customized, it will be used. Otherwise, the default type will be used. DefaultDependencyResolver is defined as follows:

Private class defadependdependencyresolver: IDependencyResolver {public object GetService (Type serviceType) {if (serviceType. isInterface | serviceType. isAbstract) {return null;} try {// if the Controller Type creates the Controller Instance Object return Activator. createInstance (serviceType);} catch {return null;} public IEnumerable <object> GetServices (Type serviceType) {return Enumerable. empty <object> ();}}

As you can see, MVC creates the Controller object through DependencyResolver. The advantage of creating an object through DependencyResolver is that the coupling between objects can be reduced. In addition, by implementing the IDependencyResolver interface, we can completely control the object creation process, for example, you can transfer the object dependency to the configuration file.

Through the above, we also know three default types: DefaultControllerFactory, defacontrocontrolleractivator, and defadependdependencyresolver, which correspond to three interfaces: IControllerFactory, IControllerActivator, and IDependencyResolver. They are designed similarly and provide an external interface. If the external interface implements this process, use it. Otherwise, use the default one. In fact, this is also our three practices involved in the Controller activation process.

Iii. Implement the IDependencyResolver Interface

Next we will use an example to prove the above process. We need to implement the IDependencyResolver interface to implement the Controller constructor injection service. For example:

public class HomeController : Controller{        private IUserService _service;  public HomeController(IUserService service)  {    _service = service;  }   public ActionResult Index()  {    return Content(_service.GetUserName());  }}


HomeController only depends on the IUserService interface and does not depend on specific objects.

Next we will implement the IDependencyResolver interface. There are many implementation methods for dependency injection. Here we use Unity. As follows:

public class UnityDependencyResolver : IDependencyResolver{  public object GetService(Type serviceType)  {    if(serviceType == null)    {      throw new ArgumentNullException("serviceType");    }          return (serviceType.IsClass && !serviceType.IsAbstract)      || Ioc.IsRegistered(serviceType) ? Ioc.GetService(serviceType) : null;  }   public IEnumerable<object> GetServices(Type serviceType)  {    if (serviceType == null)    {      throw new ArgumentNullException("serviceType");    }    return (serviceType.IsClass && !serviceType.IsAbstract)      || Ioc.IsRegistered(serviceType) ? Ioc.GetServices(serviceType) : null;  }}

Here we need to judge (serviceType. IsClass &&! ServiceType. isAbstract) | Ioc. isRegistered (serviceType) is because we have mentioned earlier that many internal MVC objects are created through the DependencyResolver component. The IConrtollerFactoy mentioned above, therefore, we are only responsible for parsing registered types or classes (non-abstract classes.

The Ioc class is very simple here, as follows:

public class Ioc{  private static IUnityContainer _container = new UnityContainer();   public static void RegisterType<TFrom,TTo>()    where TTo : TFrom  {          _container.RegisterType<TFrom, TTo>();  }   public static object GetService(Type type)  {                return _container.Resolve(type);  }   public static IEnumerable<object> GetServices(Type type)  {    return _container.ResolveAll(type);  }   public static bool IsRegistered(Type type)  {    return _container.IsRegistered(type);  }}

Then, in the Application_Start method, register the Service and set IocDependencyResolver:

Ioc. RegisterType <IUserService, UserService> ();
DependencyResolver. SetResolver (new IocDependencyResolver ());
You can see that the IUserService of the HomeController constructor is of the UserService type.

Iv. Summary

In fact, we can use IControllerFactory or IControllerActivator to achieve the same purpose in the above example. However, using IDependencyResolver is simpler, and most IOC frameworks have provided such a function. For example, the UnityDependencyResolver mentioned above does not need to be defined by itself. Unity for MVC already has such a type and can be directly used. If Autofac is used, it can be: DependencyResolver. SetResolver (new AutofacDependencyResolver (container ));

The above is all the content of this article, hoping to help you learn.

Articles you may be interested in:
  • Asp.net neatUpload supports large File Upload components
  • Asp.net does not require component URL rewriting (applicable to larger projects)
  • Implementation Code of asp.net (C #) Anti-SQL Injection component
  • Asp.net auto update component sharing
  • How to Use uploadify, A File Upload Component in asp.net (c #) development (with progress bar)
  • Introduction to the Fine Uploader File Upload Component in asp.net
  • How to convert Word to Html in asp.net (WORD components are not required)
  • Introduction to asp.net MVC implementation of image uploading without Components
  • Using the open-source component NPOI in ASP. NET to quickly Import and Export Execl data

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.