lenmom

博客园 首页 新随笔 联系 订阅 管理

背景

使用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.测试效果:

请求:

 

结果:

 

posted on 2018-03-20 15:15  老董  阅读(370)  评论(0编辑  收藏  举报