注入require对象取决于构造函数注入中的条件
我有一个界面
public interface ITrnsitReport { List GetTransitReportData (); }
它只有一个实现
public class TransitReport : ITrnsitReport { private IValidateInput _inputValidation = null; private readonly ITransitRepository _transitRepo = null; public TransitReport (IValidateInput inputValidation, ITransitRepository transitRepo) { _inputValidation = inputValidation; _transitRepo = transitRepo; } public List GetTransitReportData (string input1, string input2) { List ppdcReportList = null; bool isValid = _inputValidation.IsInputValid (input1, input2); if (isValid) { ppdcReportList = _transitRepo.GetTransitData (input1, input2); // do something with data } return ppdcReportList; } }
现在IValidateInput
有两个实现,如PPDCValidateInput
和PAIValidateInput
。 再次针对ITransitRepository
例如PPDCTransitRepository
和PAITransitRepository
。 (PAI和PPDC是业务报告,每个都有不同的validation和存储库)
我正在使用Unity Framework并将它们注册到UnityConfig.cs
。
新的我想做的是
public TransitInfo : ITransitInfo { private ITrnsitReport _report = null; public TransitInfo (ITrnsitReport report) { _report = report; } public List GetReportData (string reportType, string input1, string input2) { if (reportType.Equals ("PAI")) { _report.GetTransitReportData (input1, input2); //inject PAIValidateInput and PAITransitRepository objects } if else (reportType.Equals ("PPDC")) { _report.GetTransitReportData (input1, input2); //inject PPDCValidateInput and PPDCTransitRepository objects } } }
当它的“PAI”如何将PAIValidateInput
和PAITransitRepository
对象注入TransitReport
构造函数和“PPDC” PPDCValidateInput
和PPDCTransitRepository
对象时。
有几种方法可以去。
1.使用命名注册。
container.RegisterType("PPDC"); container.RegisterType("PAI");
在你的构造函数中:
public TransitReport ([Dependency("PPDC")]IValidateInput inputValidation, ITransitRepository transitRepo) { _inputValidation = inputValidation; _transitRepo = transitRepo; }
或者在您的注册中:
container.Register(new InjectionConstructor(new ResolvedParameter("PPDC"));
这种方法的缺点是接口的使用者需要知道它想要的接口的哪个实现,哪种打破了首先注入接口的整个问题。
2.使用枚举来定义它的validation内容。
public interface ITrnsitReport { List GetTransitReportData (); ValidateType ValidateType { get; } } public enum ValidateType { PPDC = 1, PAI = 2 }
然后在您想要使用它时选择它。
public TransitReport (IValidateInput[] inputValidation, ITransitRepository transitRepo) { _inputValidation = inputValidation.FirstOrDefault(x => x.ValidateType == ValidateType.PPC); _transitRepo = transitRepo; }
好的部分是逻辑在接口本身内部,而不是注册。 但是,它仍然需要界面的消费者知道它想要什么。
3.使用不同的界面。 (可能是我意见中最好的选择)
public interface IPAIValidateInput : IValidateInput { } public interface IPPDCValidateInput : IValidateInput { }
然后在容器中单独注册它们并注入您真正想要的界面。
public TransitReport (IPAIValidateInput inputValidation, ITransitRepository transitRepo) { _inputValidation = inputValidation; _transitRepo = transitRepo; }
需要接口而没有实际声明。 但在我的意见中,它使DI逻辑更加纯粹。
4.使用基类并将它们全部组合。
首先修复命名注册:
container.RegisterType("PPDC"); container.RegisterType("PAI"); container.RegisterType("PPDC"); container.RegisterType("PAI"); container.RegisterType("PAI"); container.RegisterType("PPDC");
然后创建一个基类
public abstract class TransitReportBase : ITrnsitReport { private readonly IValidateInput _inputValidation; private readonly ITransitRepository _transitRepo; protected TransitReportBase(IValidateInput inputValidation, ITransitRepository transitRepo) { _inputValidation = inputValidation; _transitRepo = transitRepo; } public List GetTransitReportData(string input1, string input2) { List ppdcReportList = null; bool isValid = _inputValidation.IsInputValid(input1, input2); if (isValid) { ppdcReportList = _transitRepo.GetTransitData(input1, input2); // do something with data } return ppdcReportList; } } public class PAITransitReport : TransitReportBase { public PAITransitReport([Dependency("PAI")] IValidateInput inputValidation, [Dependency("PAI")] ITransitRepository transitRepo) : base(inputValidation, transitRepo) { } } public class PPDCTransitReport : TransitReportBase { public PPDCTransitReport([Dependency("PPDC")] IValidateInput inputValidation, [Dependency("PPDC")] ITransitRepository transitRepo) : base(inputValidation, transitRepo) { } }
并使用工厂解决它们:
public class TransitReportFactory : ITransitReportFactory { private readonly IUnityContainer _container; public TransitReportFactory(IUnityContainer container) // container is injected automatically. { _container = container; } ITrnsitReport Create(string reportType) { return _container.Resolve(reportType); } }
由于PPDCTransitReport
和PAITransitReport
具体类,我们可以确保将正确的依赖项注入基类。
如何使用工厂:
首先,在Unity中注册。
container.RegisterType();
然后将其注入您的TransitInfo
。
public TransitInfo : ITransitInfo { private ITransitReportFactory _transitReportFactory; public TransitInfo (ITransitReportFactory transitReportFactory) { _transitReportFactory = transitReportFactory; } public List GetReportData (string reportType, string input1, string input2) { // Create your transitreport object. ITransitReport report = _transitReportFactory.Create(reportType); var reportData = report.GetTransitReportData (input1, input2); return reportData; } }
但我不得不说工厂本身并没有给解决方案增加太多。 如果您不介意服务定位器模式,可以将IUnityContainer
直接注入TransitInfo
。
你有几个选项,我更喜欢使用命名注册:
container.RegisterType("PPDC"); container.RegisterType("PAI");
然后,您需要使用覆盖来解析ITransitInfo:
container.Resolve(new InjectionConstructor(new ResolvedParameter("PPDC"), ...)