StructureMap DI & IoC 工具介绍
假定有这样的案例,电子商务应用程序中检索给定类别中的所有商品。我们很容易给出这样的代码
示例代码
product.cs
1: public class Product
2: {
3: }
ProductRepository.cs
1: public IList<Product> GetAllProductIn(int categoryId)
2: {
3: IList<Product> products = new List<Product>();
4:
5: //Database operation to populate products;
6:
7: return products;
8: }
ProductService.cs
1: public class ProductService
2: {
3: private ProductRepository _productRepository;
4:
5: public ProductService()
6: {
7: _productRepository = new ProductRepository();
8: }
9: public IList<Product> GetAllProductIn(int categoryId)
10: {
11: return _productRepository.GetAllProductIn(categoryId);
12: }
13: }
ProductService类负责从资源库中检索出指定类别的商品。
下面我们来分析这段代码,看看有什么问题。
用vs生成 依赖项关系图
从图中可以看出
1、ProductService类依赖于ProductRepository,如果ProductRepository类的API发生改变,ProductService就需要相应的更改。
2、代码不可测试,如果不让真正的ProductRepository类连接到真正的数据库。就不能测试ProductRepository的方法。
根据设计原则进行重构
依赖倒置原则:依赖抽象而不要依赖于具体
创建IProductRepository接口,让ProductRepository与ProductService都依赖于此接口
IProductRepository接口
1: public interface IProductRepository
2: {
3: IList<Product> GetAllProductIn(int categoryId);
4: }
ProductRepository.cs
1: public class ProductRepository :IProductRepository
2: {
3: //代码同上
4: }
ProductService.cs
1: public class ProductService
2: {
3: private IProductRepository _productRepository;
4:
5: public ProductService()
6: {
7: _productRepository = new ProductRepository();
8: }
9: }
依赖项关系图
通过引入IProductRepository接口,ProductService类只依赖于抽象而不依赖于具体。
现在ProductService类仍然负责创建具体的实现。
引入依赖注入
ProductService类仍然和ProductRepository的具体实现绑定在一起,ProductService类目前还需创建实例。
依赖注入(Dependency Injection):依赖注入是一个这样的过程,由于客户类(ProductService)只依赖于服务类的一个接口(IProductRepository),而不依赖于具体的服务类(ProductRepository),所以客户类只定义一个注入点。在程序运行过程中,客户类不直接实例化具体的服务类实例,而是客户类的运行上下文环境或专门的组件负责实例化服务类,然后将其注入到客户类中。
依赖注入的形式
1、构造器注入
ProductService.cs
1: public class ProductService
2: {
3: private IProductRepository _productRepository;
4:
5: public ProductService(IProductRepository productRepository)
6: {
7: _productRepository = productRepository;
8: }
9: public IList<Product> GetAllProductIn(int categoryId)
10: {
11: return _productRepository.GetAllProductIn(categoryId);
12: }
13: }
2、方法注入
ProductService.cs
1: public class ProductService
2: {
3: private IProductRepository _productRepository;
4:
5: public void SetRepository(IProductRepository productRepository)
6: {
7: _productRepository=productRepository;
8: }
9:
10: public ProductService( )
11: {
12: }
13: public IList<Product> GetAllProductIn(int categoryId)
14: {
15: return _productRepository.GetAllProductIn(categoryId);
16: }
17: }
18:
IoC
定义:控制反转(Inversion of Control,英文缩写为IoC)是一种设计模式,核心思想是类之间的依赖关系,不再由类自己去负责,而是由容器根据配置文件去创建实例并维护各个实例之间的依赖关系。
DI是实现IoC的一种方式。
StructureMap
StructureMap是一种.Net下的依赖注入框架,当前版本是2.6.1,下载地址https://github.com/structuremap/structuremap/downloads
1: public static class ContainerBootstrapper
2: {
3: public static void BootstrapStructureMap()
4: {
5: // Initialize the static ObjectFactory container
6: ObjectFactory.Initialize(x =>
7: {
8: x.For<IProductRepository>().Use<ProductRepository>();
9: });
10: }
11: }
调用
1: class Program
2: {
3: static void Main(string[] args)
4: {
5: ContainerBootstrapper.BootstrapStructureMap();
6: ProductService service = new ProductService(ObjectFactory.GetInstance<IProductRepository>());
7: service.GetAllProductIn(2);
8:
9: }
10: }