注入需要对象取决于构造函数注入中的条件
Inject require object depends on condition in constructor injection
我有接口
public interface ITrnsitReport
{
List<UserDefinedType> 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<UserDefinedType> GetTransitReportData (string input1, string input2)
{
List<UserDefinedType> 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 是业务报告,每个都有不同的验证和存储库)
我正在使用 Unity Framework 并让他们将它们注册到 UnityConfig.cs
。
我正在尝试做的新事情是
public TransitInfo : ITransitInfo
{
private ITrnsitReport _report = null;
public TransitInfo (ITrnsitReport report)
{
_report = report;
}
public List<UserDefinedType> 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
个对象。
您有多种选择,我更喜欢的一种是使用命名注册:
container.RegisterType<IValidateInput, PPDCValidateInput>("PPDC");
container.RegisterType<IValidateInput, PAIValidateInput>("PAI");
然后您需要使用覆盖解析 ITransitInfo:
container.Resolve<ITransitInfo>(new InjectionConstructor(new ResolvedParameter<IValidateInput>("PPDC"), ...)
有几种方法。
1. 使用命名注册。
container.RegisterType<IValidateInput, PPDCValidateInput>("PPDC");
container.RegisterType<IValidateInput, PAIValidateInput>("PAI");
在你的构造函数中:
public TransitReport ([Dependency("PPDC")]IValidateInput inputValidation,
ITransitRepository transitRepo)
{
_inputValidation = inputValidation;
_transitRepo = transitRepo;
}
或在您的注册中:
container.Register<ITrnsitReport>(new InjectionConstructor(new ResolvedParameter<IValidateInput>("PPDC"));
这种方法的缺点是接口的使用者需要知道它想要接口的哪种实现,这首先打破了注入接口的整个想法。
2. 使用枚举来定义它正在验证的内容。
public interface ITrnsitReport
{
List<UserDefinedType> GetTransitReportData ();
ValidateType ValidateType { get; }
}
public enum ValidateType
{
PPDC = 1,
PAI = 2
}
然后 select 当你想用它的时候。
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.使用一个基数class,然后将它们全部组合起来。
首先修复命名注册:
container.RegisterType<IValidateInput, PPDCValidateInput>("PPDC");
container.RegisterType<IValidateInput, PAIValidateInput>("PAI");
container.RegisterType<ITransitRepository, PPDCTransitRepository>("PPDC");
container.RegisterType<ITransitRepository, PAITransitRepository>("PAI");
container.RegisterType<ITransitReport, PAITransitReport>("PAI");
container.RegisterType<ITransitReport, PPDCTransitReport>("PPDC");
然后创建基地class
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<UserDefinedType> GetTransitReportData(string input1, string input2)
{
List<UserDefinedType> 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<ITrnsitReport>(reportType);
}
}
感谢具体的 classes PPDCTransitReport
和 PAITransitReport
我们可以确保将正确的依赖项注入基础 class.
工厂使用方法:
首先,用Unity注册。
container.RegisterType<ITransitReportFactory, TransitReportFactory>();
然后注入你的TransitInfo
.
public TransitInfo : ITransitInfo
{
private ITransitReportFactory _transitReportFactory;
public TransitInfo (ITransitReportFactory transitReportFactory)
{
_transitReportFactory = transitReportFactory;
}
public List<UserDefinedType> 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
.
我有接口
public interface ITrnsitReport
{
List<UserDefinedType> 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<UserDefinedType> GetTransitReportData (string input1, string input2)
{
List<UserDefinedType> 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 是业务报告,每个都有不同的验证和存储库)
我正在使用 Unity Framework 并让他们将它们注册到 UnityConfig.cs
。
我正在尝试做的新事情是
public TransitInfo : ITransitInfo
{
private ITrnsitReport _report = null;
public TransitInfo (ITrnsitReport report)
{
_report = report;
}
public List<UserDefinedType> 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
个对象。
您有多种选择,我更喜欢的一种是使用命名注册:
container.RegisterType<IValidateInput, PPDCValidateInput>("PPDC");
container.RegisterType<IValidateInput, PAIValidateInput>("PAI");
然后您需要使用覆盖解析 ITransitInfo:
container.Resolve<ITransitInfo>(new InjectionConstructor(new ResolvedParameter<IValidateInput>("PPDC"), ...)
有几种方法。
1. 使用命名注册。
container.RegisterType<IValidateInput, PPDCValidateInput>("PPDC");
container.RegisterType<IValidateInput, PAIValidateInput>("PAI");
在你的构造函数中:
public TransitReport ([Dependency("PPDC")]IValidateInput inputValidation,
ITransitRepository transitRepo)
{
_inputValidation = inputValidation;
_transitRepo = transitRepo;
}
或在您的注册中:
container.Register<ITrnsitReport>(new InjectionConstructor(new ResolvedParameter<IValidateInput>("PPDC"));
这种方法的缺点是接口的使用者需要知道它想要接口的哪种实现,这首先打破了注入接口的整个想法。
2. 使用枚举来定义它正在验证的内容。
public interface ITrnsitReport
{
List<UserDefinedType> GetTransitReportData ();
ValidateType ValidateType { get; }
}
public enum ValidateType
{
PPDC = 1,
PAI = 2
}
然后 select 当你想用它的时候。
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.使用一个基数class,然后将它们全部组合起来。
首先修复命名注册:
container.RegisterType<IValidateInput, PPDCValidateInput>("PPDC");
container.RegisterType<IValidateInput, PAIValidateInput>("PAI");
container.RegisterType<ITransitRepository, PPDCTransitRepository>("PPDC");
container.RegisterType<ITransitRepository, PAITransitRepository>("PAI");
container.RegisterType<ITransitReport, PAITransitReport>("PAI");
container.RegisterType<ITransitReport, PPDCTransitReport>("PPDC");
然后创建基地class
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<UserDefinedType> GetTransitReportData(string input1, string input2)
{
List<UserDefinedType> 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<ITrnsitReport>(reportType);
}
}
感谢具体的 classes PPDCTransitReport
和 PAITransitReport
我们可以确保将正确的依赖项注入基础 class.
工厂使用方法:
首先,用Unity注册。
container.RegisterType<ITransitReportFactory, TransitReportFactory>();
然后注入你的TransitInfo
.
public TransitInfo : ITransitInfo
{
private ITransitReportFactory _transitReportFactory;
public TransitInfo (ITransitReportFactory transitReportFactory)
{
_transitReportFactory = transitReportFactory;
}
public List<UserDefinedType> 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
.