AutoFac實現WebAPI依賴注入(EF以及Mysql)

什麼是依賴注入?mysql

咱們以實際的例子來加以介紹
實體以下
  public class Product
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
    }
EF的實現以下
 public class ProductContext: DbContext
    {
        public ProductContext(): base( "ProductContext")
        {

        }
        public DbSet< Product> Products { get; set; }
    }
  public class ProductRepo_EF 
    {
        private ProductContext _ctx = new ProductContext (); 
        public IEnumerable<Models.Product > GetAll()
        {
            return _ctx.Products.ToList();
        }

        public Models. Product GetProduct( int id)
        {
            return _ctx.Products.FirstOrDefault(x=>x.ID==id);
        }
    }
在controller中
public class ProductsController : ApiController{
    //這一行是問題根源所在
    ProductRepository _repository = new ProductRepository();

    public IEnumerable<Product> Get()
    {
        return _repository.GetAll();
    }

    public IHttpActionResult Get(int id)
    {
        var product = _repository.GetByID(id);
        if (product == null)
        {
            return NotFound();
        }
        return Ok(product);
    }}
咱們的productController是依賴於productRespository來提供數據的,也就是咱們形象的說法,這個controller依賴於_respository的實現。那若是咱們的repo發生變化,甚至咱們將不許備採用EF針對sqlserver提供的方式,咱們想更換針對mysql的實現,若是有不少controller都依賴於repo的實現,那代碼的改動量將會很巨大,並且很容易犯錯。這在真正的工業代碼中將是沒法想象的。 因此咱們必須採用以來注入的鬆耦合實現方式。
public interface IProductRepository{
    IEnumerable<Product> GetAll();
    Product GetById(int id);
    }

public class ProductRepository : IProductRepository{
    
//
}

public class ProductsController : ApiController{
    private IProductRepository _repository;

    public ProductsController(IProductRepository repository)  
    {
        _repository = repository;
    }

  } 

利用構造函數向外界暴露依賴,這樣在再建立不一樣的實例的時候,只須要提供不一樣的實現就能夠了,在代碼內部則不會發生改動。關於更多依賴注入的基礎知識,能夠自行搜索,實在太多。咱們這裏針對webapi的依賴注入。 在mvc以及webapi中,與業務邏輯打交道,那就確定少不了controller對於業務類(比方說Repo)的依賴。那這裏想要實現解耦,就要控制controller實例的建立,可是在mvc框架中controller的建立是由框架自行完成的..頓時以爲無從下手了。在mvc2.0中,若是使用DefaultControllerFactory的實現,建立controller實例是經過反射調用無參構造函數來實現的。那咱們想要使用默認工廠來經過構造函數注入,顯然是不現實的。只能總體更換整個工廠。而隨着mvc框架的發展,到mvc4的時候,框架已經對於外部的以來注入實現已經至關友好了。默認工廠再也不經過單一的無參構造函數反射建立實例,而是統一的經過IDependencyresolver接口提供的 IDependencyResolver.GetService(Type serviceType)
方法來暴露實現。在建立controller實例的時候,首先經過該方法去取得controller實例,若是爲null在調用無參構造建立實例。 因此咱們只須要使用外部IOC容器擴展針對IDependencyResolver的實現便可。 外部IOC容器經常使用的有 Unity Autofac Ninject 等等。咱們這裏採用AutoFac作爲咱們的實現。由於文檔齊全,效率高,功能強大,也是主流IOC容器。 使用autofac能夠自行建立,也能夠採用autofac官方針對webapi的擴展。 經過Nuget安裝 autofac 以及autofac.extentions.webapi。將自動有AutofacWebApiDependencyResolver實現。
web

在global.asax中

var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());           
//僅僅這一個地方的改動,就達到了對數據庫的無縫連接。
builder.RegisterType<ProductRepo_EF>().As<IProductRepo>();           
var container = builder.Build();           
var resolver = new AutofacWebApiDependencyResolver(container);            
GlobalConfiguration.Configuration.DependencyResolver = resolver;
在這裏咱們使用了EF和EF to Mysql兩種repo實現,也就是經過兩種數據庫提供數據。
備註一下,使用EF To Mysql須要安裝mysql數據庫,以及在nuget包中


 
      
而且在web.config中提供mysql以及sqlserver兩種鏈接字符串便可。
這樣 ,當咱們須要更換不一樣的repo實現的時候只須要在
builder.RegisterType< ProductRepo_EF >().As< IProductRepo >();   
替換成
builder.RegisterType< ProductRepo_Mysql >().As< IProductRepo >(); 便可。
咱們的代碼改動僅僅只發生在注入的這一個地方。
相關文章
相關標籤/搜索