什么是依赖注入?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实现的时候只须要在
替换成