Dependency injection in ASP. NET Web API

Source: Internet
Author: User

What is Dependency injection
Dependency, which is another object that an object needs, for example, this is a store that we typically define to handle data access, let's use an example to explain, first, define a domain model as follows:
Namespace Pattern.DI.MVC.Models
{
public class Product
{
public int Id {get; set;}
public string Name {get; set;}
Public decimal price {get; set;}
}
}
Then there is a simple storage class for the instance:
Namespace Pattern.DI.MVC.Models
{
public class Productcontext
{
Public list<product> Products {get; internal set;}
Public Productcontext ()
{
Products.add (New Product () {Id = 1, Name = "Aunt Cang", price = 100});
Products.add (New Product () {Id = 2, Name = "Muto granny", price = 200});
Products.add (New Product () {Id = 3, Name = "Sister Ozawa", Price = 300});
}
}
public class Productrepository
{
Private Productcontext context=new productcontext ();
Public ienumerable<product> GetAll ()
{
Return to context. Products;
}
Public Product GetById (int id)
{
Return to context. Products.firstordefault (p = = P.id = = Id);
}
}
}
Now, we define an ASP. NET WEB API controller to support get requests to the product entity set:
Namespace Pattern.DI.MVC.Controllers
{
public class Productcontroller:apicontroller
{
Private readonly productrepository productrepository=new productrepository ();
Public ienumerable<product> Get ()
{
return Productrepository.getall ();
}
Public Product Get (int id)
{
return Productrepository.getbyid (ID);
}
}
}
Now notice that this controller relies on the "Productrepository" class, we instantiate the productrepository in the class, this is the "bad taste" of the design, because of the following reasons:
If you want to use another implementation to replace Productrepository, you also have to modify the Productcontroller class;
If productrepository exists, you have to configure them in Productcontroller, and for a large project with many controllers, you will be able to drill down to wherever possible;
It's hard to do unit tests because the controller has hard-coded queries to the database, and for a unit test, you can use a clone of the pile storage before you have the exact design.
We can solve this problem by injecting a productrepsoitory, first refactoring the Productrepository method into one socket:
Namespace Pattern.DI.MVC.Models
{
public interface Iproductrepository
{
Ienumerable<product> GetAll ();
Product GetById (int id);
}
public class Productrepository:iproductrepository
{
Private Productcontext context = new Productcontext ();
Public ienumerable<product> GetAll ()
{
Return to context. Products;
}
Public Product GetById (int id)
{
Return to context. Products.firstordefault (p = = P.id = = Id);
}
}
}
Then use the parameters in the Productc0ntroller to pass in the iproductrepository:
Namespace Pattern.DI.MVC.Controllers
{
public class Productcontroller:apicontroller
{
Private ReadOnly iproductrepository productrepository;
Public Productcontroller (Iproductrepository productrepository)
{
This.productrepository = productrepository;
}
Public ienumerable<product> Get ()
{
return Productrepository.getall ();
}
Public Product Get (int id)
{
return Productrepository.getbyid (ID);
}
}
}
This example uses constructor injection, and you can also use the method of the set-up injection, where the ASP. NET WEB API creates the controller after mapping the route for the request, and now he doesn't know any details about iproductrepository, which is resolved through the API dependency.
ASP. NET Web API Dependency Parser
The ASP. NET Web API defines a idependencyresolever used to parse a dependent project, the following is the definition of this interface:
Public interface Idependencyresolver:idependencyscope, IDisposable
{
Idependencyscope BeginScope ();
}
public interface Idependencyscope:idisposable
{
Object GetService (Type servicetype);
Ienumerable<object> getservices (Type servicetype);
}
There are two methods of this interface
GetService creates an instance for a type;
GetServices creating an instance collection for a specific type
This interface inherits from Idependencyscope and adds the BeginScope method, which is discussed next in this article.
When the ASP. NET WEB API creates a controller instance, it first calls Idependencyresolver's GetService method, returns a controller instance, You can use an extended hook to create a controller and resolve dependencies. If the GetService method returns null,asp.net the Web API will look for a parameterless constructor.
Using Unity to resolve dependencies
While you can start writing a idenpendencyresolver implementation from scratch, this interface has been designed to be a bridge between the ASP and IOC tools.
The IOC container is a build for managing dependent projects, where you can register types, create objects when used, and IOC will easily resolve dependent relationships automatically, and many IOC containers allow you to control the object's life cycle.
First install unity in the project using the NuGet package Manage console, the introduction to unity can be found here for details.
Install-package Unity
The following is an implementation of idependencyresolver using the Unity container:
Using System;
Using System.Collections.Generic;
Using System.Linq;
Using System.Web;
Using Microsoft.Practices.Unity;
Using System.Web.Http.Dependencies;
Namespace Pattern.DI.MVC.Models
{
public class Unityresolver:idependencyresolver
{
protected Iunitycontainer container;
Public unityresolver (Iunitycontainer container)
{
if (container = = null)
{
throw new ArgumentNullException ("container");
}
This.container = container;
}
public Object GetService (Type servicetype)
{
Try
{
Return container. Resolve (servicetype);
}
catch (Resolutionfailedexception)
{
return null;
}
}
Public ienumerable<object> getservices (Type servicetype)
{
Try
{
Return container. ResolveAll (servicetype);
}
catch (Resolutionfailedexception)
{
return new list<object> ();
}
}
Public Idependencyscope BeginScope ()
{
var child = container. Createchildcontainer ();
return new Unityresolver (child);
}
public void Dispose ()
{
Container. Dispose ();
}
}
}
Configuring dependency resolution
The dependency resolver is set on the Dependencyresolver property in the global Httpconfiguration object, and the following code uses unity to register the Iproductrepository interface and create a unityresolver, Modify the Register method in App_start/webapiconfig.csTOEFL Answers
Namespace Pattern.DI.MVC
{
public static Class Webapiconfig
{
public static void Register (Httpconfiguration config)
{
var container = new UnityContainer ();
Container. Registertype<iproductrepository, productrepository> ();
Config. Dependencyresolver = new Unityresolver (container);
Config. Routes.maphttproute (
Name: "Defaultapi",
Routetemplate: "Api/{controller}/{id}",
defaults:new {id = routeparameter.optional}
);
}
}
}

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.