• Autofac容器使用属性进行WebApi自动注入


    背景

    使用Autofac进行依赖注入时,经常遇到的场景是在容器中进行类似如下代码的注入操作:

    builder.RegisterType<BackInStockSubscriptionService>().As<IBackInStockSubscriptionService>().InstancePerLifetimeScope();
    builder.RegisterType<CategoryService>().As<ICategoryService>().InstancePerLifetimeScope();
    builder.RegisterType<CompareProductsService>().As<ICompareProductsService>().InstancePerLifetimeScope();
    builder.RegisterType<RecentlyViewedProductsService>().As<IRecentlyViewedProductsService>().InstancePerLifetimeScope();
    builder.RegisterType<ManufacturerService>().As<IManufacturerService>().InstancePerLifetimeScope();
    builder.RegisterType<PriceFormatter>().As<IPriceFormatter>().InstancePerLifetimeScope();
    builder.RegisterType<ProductAttributeFormatter>().As<IProductAttributeFormatter>().InstancePerLifetimeScope();
    builder.RegisterType<ProductAttributeParser>().As<IProductAttributeParser>().InstancePerLifetimeScope();

    因为这种注入是统一进行的,随着项目规模的扩大和代码复杂度的增加,需要在注册的地方不断地增加新的类来注册类型,这样会使代码失去了开闭原则:对修改关闭,对扩展开放。

    解决方案

    1. 定义一个属性用于标识类的注入意图,在应用初始化时利用反射进行集中类型注册。

        public class InjectableAttribute : Attribute
        {
    
        }

    2. 在需要注入的类型中,使用[Injectable]标记注入

     public class Employee
        {
            public string Name { get; set; }
    
            public string Password { get; set; }
        }
    
        public interface IEmployeeManager
        {
            IList<Employee> GetAllEmployess();
        }
    
        public interface IEmployeeRepository
        {
            IList<Employee> GetAllEmployess();
        }
    
        [Injectable]
        public class EmployeeRepository : IEmployeeRepository
        {
            public IList<Employee> GetAllEmployess()
            {
                List<Employee> list = new List<Employee>();
                list.Add(new Employee { Name = "a", Password = "b" });
                return list;
            }
        }
    
    
        [Injectable]
        public class EmployeeManager : IEmployeeManager
        {
            private readonly IEmployeeRepository _employeeRepository;
    
            public EmployeeManager(IEmployeeRepository employeeRepository)
            {
                _employeeRepository = employeeRepository;
            }
    
            public IList<Employee> GetAllEmployess()
            {
                var employeeData = _employeeRepository.GetAllEmployess();
                var employeeList = new List<Employee>();
                foreach (var employee in employeeData)
                {
                    var employ = new Employee();
                    employ.Password= employee.Password;
                    employ.Name = employee.Name;
                    employeeList.Add(employ);
                }
                return employeeList;
            }
        }

    3. 在WebApi的Controller中进行注入操作

     public class EmployeeController : ApiController
        {
            private readonly IEmployeeManager _employeeManager;
    
            public EmployeeController(IEmployeeManager employeeManager)
            {
                _employeeManager = employeeManager;
            }
    
            [AllowAnonymous]
            [ResponseType(typeof(Employee))]
            public IHttpActionResult GetEmployees()
            {
                var employeeData = _employeeManager.GetAllEmployess();
                return Ok(employeeData);
            }
        }

    4. 项目中引用 Autofac.WebApi2 and AutoFac,定义如下容器初始化类

     public static class AutofacDependecyBuilder
        {
            public static void DependencyBuilder()
            {
                // Create the builder with which components/services are registered.
                var builder = new ContainerBuilder();
    
                // Register your Web API controllers.
                builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
    
                builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
                                          .Where(t => t.GetCustomAttribute<InjectableAttribute>() != null)
                                          .AsImplementedInterfaces()
                                          .InstancePerRequest();
    
                builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
    
                //Build the Container
                var container = builder.Build();
    
                //Create the Dependency Resolver
                AutofacWebApiDependencyResolver resolver = new AutofacWebApiDependencyResolver(container);
    
                //Configuring WebApi with Dependency Resolver
                GlobalConfiguration.Configuration.DependencyResolver = resolver;
    
            }
    
        }

    5. 在Web程序开始处调用容器注册

        public class WebApiApplication : System.Web.HttpApplication
        {
            protected void Application_Start()
            {
                GlobalConfiguration.Configure(WebApiConfig.Register);
                RouteConfig.RegisterRoutes(RouteTable.Routes);
    
                AutofacDependecyBuilder.DependencyBuilder();
            }
        }

    6.测试效果:

    请求:

    结果:

  • 相关阅读:
    使用QT在子线程中访问串口
    小程序批量上传图片方案
    Jenkins自动化远程部署(vue-github)
    nginx配置https证书
    Linux 安装php7
    Vue技术点整理-指令
    如何保证接口的幂等性?
    mybatis 一对多分页查询数据条数不匹配解决
    源码系列-JDK-String
    kafka window 操作
  • 原文地址:https://www.cnblogs.com/lenmom/p/8609439.html
Copyright © 2020-2023  润新知