• AutoFac实现WebAPI依赖注入(EF以及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实现。

    在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>(); 即可。
    我们的代码改动仅仅只发生在注入的这一个地方。
  • 相关阅读:
    银行卡号每隔四位添加一个分隔符
    clipboard.js实现文本复制
    选中|复制文本
    react---之下拉菜单默认选中的值始终不变的问题
    create-react-app支持less配置
    数对
    安置路灯
    被三整除
    牛牛找工作
    C++ std::pair
  • 原文地址:https://www.cnblogs.com/JasonShenW/p/5340061.html
Copyright © 2020-2023  润新知