如何为工厂类创建的类实现依赖注入?
问题描述
假设有一个定义了startProcessing()方法的ICustomer接口:
interface ICustomer { void startProcessing(byte[] data); }
现有多个实现了ICustomer接口的具体类,如ProductA_User和ProductB_User:
class ProductA_User : ICustomer { string _name; IRepository _repo; public ProductA_User(string name) { _name = name; } public void startProcessing(byte[] data) { Console.WriteLine(_name); var temp = _repo.Get<VModel>(filter: x.CName == _name).ToList(); } } class ProductB_User : ICustomer { public void startProcessing(byte[] data) { throw new System.NotImplementedException(); } }
目前通过MemberFactory工厂类的Create方法,根据ProductTypeEnum枚举创建对应ICustomer实例:
enum ProductTypeEnum { ProductA, ProductB } class MemberFactory { ICustomer Create(ProductTypeEnum productType) { switch (productType) { case ProductTypeEnum.ProductA: return new ProductA_User("Steve"); case ProductTypeEnum.ProductB: return new ProductB_User(); default: return null; } } }
其中ProductA_User需要注入EF仓储IRepository,但不想通过构造函数额外传递_repo参数,请问该如何为这些具体类实现依赖注入?
解决方案
1. 改造工厂类,从DI容器获取依赖
让工厂类依赖DI容器(比如ASP.NET Core的IServiceProvider),在创建实例时从容器中取出IRepository,通过属性注入给ProductA_User:
首先修改ProductA_User,把私有_repo字段改为可设置的属性:
class ProductA_User : ICustomer { string _name; public IRepository Repo { get; set; } // 改为公共属性用于注入 public ProductA_User(string name) { _name = name; } public void startProcessing(byte[] data) { Console.WriteLine(_name); var temp = Repo.Get<VModel>(filter: x.CName == _name).ToList(); } }
然后改造MemberFactory,注入IServiceProvider并完成依赖注入:
class MemberFactory { private readonly IServiceProvider _serviceProvider; // 构造注入IServiceProvider public MemberFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public ICustomer Create(ProductTypeEnum productType) { switch (productType) { case ProductTypeEnum.ProductA: var user = new ProductA_User("Steve"); // 从容器取出IRepository实例赋值给属性 user.Repo = _serviceProvider.GetRequiredService<IRepository>(); return user; case ProductTypeEnum.ProductB: return _serviceProvider.GetRequiredService<ProductB_User>(); default: return null; } } }
2. 直接用DI容器注册工厂委托(推荐)
不需要手写MemberFactory,直接在DI容器中注册一个工厂委托,让容器自动处理依赖注入。以ASP.NET Core为例:
在服务注册代码中(如Program.cs):
// 先注册IRepository的实现 builder.Services.AddScoped<IRepository, EfRepository>(); // 注册ProductB_User builder.Services.AddScoped<ProductB_User>(); // 注册ICustomer的工厂委托 builder.Services.AddScoped<Func<ProductTypeEnum, ICustomer>>(serviceProvider => productType => { switch (productType) { case ProductTypeEnum.ProductA: var repo = serviceProvider.GetRequiredService<IRepository>(); return new ProductA_User("Steve") { Repo = repo }; case ProductTypeEnum.ProductB: return serviceProvider.GetRequiredService<ProductB_User>(); default: throw new ArgumentOutOfRangeException(nameof(productType)); } });
后续需要创建ICustomer实例时,直接注入这个委托并调用:
public class BusinessService { private readonly Func<ProductTypeEnum, ICustomer> _customerFactory; public BusinessService(Func<ProductTypeEnum, ICustomer> customerFactory) { _customerFactory = customerFactory; } public void ProcessData(ProductTypeEnum type, byte[] data) { var customer = _customerFactory(type); customer.startProcessing(data); } }
3. 使用支持属性注入的DI容器(如Autofac)
如果使用Autofac这类框架,可以直接配置属性注入,无需手动赋值:
首先注册组件时启用属性注入:
var containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType<EfRepository>().As<IRepository>(); containerBuilder.RegisterType<ProductB_User>().As<ICustomer>(); // 注册ProductA_User并启用属性注入 containerBuilder.Register(c => new ProductA_User("Steve")) .As<ICustomer>() .PropertiesAutowired();
然后工厂类从容器中解析实例即可:
class MemberFactory { private readonly IContainer _container; public MemberFactory(IContainer container) { _container = container; } public ICustomer Create(ProductTypeEnum productType) { switch (productType) { case ProductTypeEnum.ProductA: return _container.Resolve<ICustomer>(); case ProductTypeEnum.ProductB: return _container.Resolve<ProductB_User>(); default: return null; } } }
内容的提问来源于stack exchange,提问作者tt0206
相关产品推荐
相关产品推荐

