在软件开发中,依赖注入(Dependency Injection,简称DI)是一种设计模式,用于实现控制反转(Inversion of Control,简称IoC),它允许程序在运行时动态地将依赖项注入到对象中。这种方式可以提高代码的可测试性和可维护性,但随着项目的增长,依赖项的注册可能会变得冗长且难以管理。本文将探讨如何使用AutoFacWebApi容器作为依赖注入解析器来减少代码冗余,并遵循SOLID原则。
当开始使用任何容器来解析项目中的依赖时,通常会编写大量的冗余代码,如下所示:
builder.RegisterType<EmployeeManager>().As<IEmployeeManager>();
builder.RegisterType<CustomerManager>().As<ICustomerManager>();
builder.RegisterType<EmployeeRepository>().As<IEmployeeRepository>();
builder.RegisterType<CustomerRepository>().As<ICustomerRepository>();
随着项目的增长,依赖构建器中的代码行数也会增加,这会带来多个问题:
将通过属性和反射来解决代码冗余问题。
首先,将在项目中创建一个公共库,并在System命名空间下创建一个继承自Attribute类的InjectableAttribute类。
using System;
namespace AutoFacCommon
{
public class InjectableAttribute : Attribute
{
}
}
这里使用了"InjectableAttribute"作为名称,因为Angular2有一个名为Injectable的依赖注入,希望客户端和服务端能够同步。
接下来,需要使用Injectable属性来装饰类。
[Injectable]
public class EmployeeManager : IEmployeeManager
{
private readonly IEmployeeRepository _employeeRepository;
public EmployeeManager(IEmployeeRepository employeeRepository)
{
_employeeRepository = employeeRepository;
}
public IList<Employee> GetAllEmployess()
{
var employeeData = _employeeRepository.GetAllEmployees();
var employeeList = new List<Employee>();
foreach (var employee in employeeData)
{
var employ = new Employee();
employ.EmployeeDesignation = employee.EmployeeDesignation;
employ.EmployeeId = employee.EmployeeId;
employ.EmployeeName = employee.EmployeeName;
employeeList.Add(employ);
}
return employeeList;
}
}
注意:当看到类上装饰了[Injectable]属性时,这意味着这个类已经准备好被注入了。在需要这个类的地方都可以使用。
现在让在WebApi控制器中注入这个类。
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);
}
}
运行上述代码时,可能会发现它不会工作,因为还没有告诉CLR来解析依赖。现在来做这件事。
需要有Autofac.WebApi2和AutoFac。可以从Nuget包管理器下载。
public static class AutofacDependencyBuilder
{
public static void DependencyBuilder()
{
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.Where(t => t.GetCustomAttribute<InjectableAttribute>() != null)
.AsImplementedInterfaces().InstancePerRequest();
builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
var container = builder.Build();
var resolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
}
}
上述代码将把所有部分整合在一起。这段代码将在项目首次加载时加载所有程序集。它将使用反射获取所有自定义属性,并为每个请求创建实例。在例子中,它是Injectable自定义属性。
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
AutofacDependencyBuilder.DependencyBuilder();
}
}