我有一个界面
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
对象。
有几种方法。
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
}
然后在要使用它时选择它。
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<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");
然后创建一个基类
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);
}
}
多亏了具体的类PPDCTransitReport
,PAITransitReport
我们可以确保将正确的依赖项注入到基类中。
如何使用工厂:
首先,向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
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句