什麼是依賴注入?mysql
public class Product { public int ID { get; set; } public string Name { get; set; } public decimal Price { get; set; } }
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); } }
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實現的時候只須要在
替換成