在现代软件开发中,依赖注入(DI)是一种非常流行的设计范式。它允许编写松耦合的代码,消除对象之间的紧密耦合,使对象和使用它们的应用程序更加灵活、可重用、易于测试,并且可以在运行时和编译时进行更改。本文将讨论依赖注入如何帮助构建松耦合的软件架构,以及如何使用Autofac实现DI。
有四种主要方式可以将依赖注入到一个类中,例如构造函数注入、设置器注入、属性注入和方法注入。本文将讨论构造函数注入以及如何使用Autofac实现DI。
这是最常见的DI方法。在这种方法中,在构造函数本身中传递对象引用。因此,当客户端创建对象时,它会在构造函数中传递对象。依赖注入是通过在实例化类时通过类的构造函数提供依赖项来完成的。注入的组件可以在类中的任何地方使用。
public class Customer
{
DIDbContext dbContext = new DIDbContext();
public int Create(Customer customer)
{
if (customer != null)
{
dbContext.Customers.Add(customer);
dbContext.SaveChanges();
return 1;
}
return 0;
}
public IEnumerable GetAllCustomers()
{
return dbContext.Customers.ToList();
}
}
在上面的代码中,CustomerController类依赖于Customer类。在这种情况下,CustomerController直接在CustomerController构造函数内部创建Customer实例,并且确切知道它正在创建和消费的Customer类的类型。这违反了依赖倒置原则(DIP)。
为了减少依赖,需要执行几个步骤。首先,引入了Repository层,可以在这里保留与数据库相关的功能,如数据插入、修改和获取。然后引入了服务层,如果需要,可以在这里保留额外的逻辑。例如,如果需要向客户发送邮件,或者如果需要计算客户的总利润,可以在服务层保留邮件发送和计算功能。在这种情况下,可以在Customer和CustomerController之间创建两个抽象层。可以使用接口/抽象类来表示Customer和CustomerController之间的抽象。
public interface IRepository
{
int Create(T t);
IEnumerable FindAll();
T FindById(int id);
}
public class CustomerRepository : IRepository
{
DIDbContext dbContext = new DIDbContext();
public int Create(Customer customer)
{
if (customer != null)
{
dbContext.Customers.Add(customer);
dbContext.SaveChanges();
return 1;
}
return 0;
}
public IEnumerable FindAll()
{
return dbContext.Customers.ToList();
}
public Customer FindById(int id)
{
return dbContext.Customers.Find(id);
}
}
public interface IService
{
int Create(T t);
IEnumerable FindAll();
T FindById(int id);
void SendMail();
void CalculateTotalProfit();
}
public class CustomerService : IService
{
private readonly IRepository _iCustomerRepository;
public CustomerService(IRepository customerRepository)
{
_iCustomerRepository = customerRepository;
}
public int Create(Customer customer)
{
return _iCustomerRepository.Create(customer);
}
public IEnumerable FindAll()
{
return _iCustomerRepository.FindAll();
}
public Customer FindById(int id)
{
return _iCustomerRepository.FindById(id);
}
public void SendMail()
{
// 实现此处...
}
public void CalculateTotalProfit()
{
// 实现此处...
}
}
public class CustomerController : Controller
{
private readonly IService _customerService = null;
public CustomerController(IService customerService)
{
_customerService = customerService;
}
public ActionResult Index()
{
var customers = _customerService.FindAll();
return View(customers);
}
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(Customer customer)
{
_customerService.Create(customer);
return RedirectToAction("Index");
}
}
在这里,引入了两个接口IRepository和IService,以表示抽象,并确保CustomerController类只调用IService接口中的方法或属性,因为CustomerController类依赖于Service类,而Customer类调用IRepository接口中的方法或属性,因为Customer类依赖于Repository类。
Autofac是一个IoC容器,为ASP.NET MVC框架提供了更好的集成,并管理类之间的依赖关系,使应用程序更容易更改。可以轻松地将Autofac集成到应用程序中;为此,首先需要获取NuGet包。如果不熟悉NuGet,可以从此网站下载Autofac。
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterType(typeof(CustomerService)).AsImplementedInterfaces();
builder.RegisterType(typeof(CustomerRepository)).AsImplementedInterfaces();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));