注入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有两个实现,如PPDCValidateInputPAIValidateInput 。 再次针对ITransitRepository例如PPDCTransitRepositoryPAITransitRepository 。 (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”如何将PAIValidateInputPAITransitRepository对象注入TransitReport构造函数和“PPDC” PPDCValidateInputPPDCTransitRepository对象时。

有几种方法可以去。

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); } } 

由于PPDCTransitReportPAITransitReport具体类,我们可以确保将正确的依赖项注入基类。

如何使用工厂:

首先,在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"), ...)