Es gibt mehrere Möglichkeiten.
1. Verwenden genannt Registrierungen.
container.RegisterType<IValidateInput, PPDCValidateInput>("PPDC");
container.RegisterType<IValidateInput, PAIValidateInput>("PAI");
Und in Ihrem Konstruktor:
public TransitReport ([Dependency("PPDC")]IValidateInput inputValidation,
ITransitRepository transitRepo)
{
_inputValidation = inputValidation;
_transitRepo = transitRepo;
}
Oder in Ihrer Registrierung:
container.Register<ITrnsitReport>(new InjectionConstructor(new ResolvedParameter<IValidateInput>("PPDC"));
Der Nachteil bei diesem Ansatz ist, dass der Verbraucher der Schnittstelle, die Umsetzung der wissen muss, Schnittstelle, die es will, die die ganze Idéa des Einspritzens einer Schnittstelle in erster Linie bricht.
2. Verwenden Sie eine Enum zu definieren, was es zu validieren.
public interface ITrnsitReport
{
List<UserDefinedType> GetTransitReportData();
ValidateType ValidateType { get; }
}
public enum ValidateType
{
PPDC = 1,
PAI = 2
}
Und dann wählen Sie es aus, wenn Sie es verwenden möchten.
public TransitReport (IValidateInput[] inputValidation,
ITransitRepository transitRepo)
{
_inputValidation = inputValidation.FirstOrDefault(x => x.ValidateType == ValidateType.PPC);
_transitRepo = transitRepo;
}
Der gute Teil ist, dass die Logik innerhalb der Schnittstelle selbst ist, und nicht in Bezug auf die Registrierung. Es erfordert jedoch immer noch, dass der Verbraucher der Schnittstelle weiß, was er will.
3. Verwenden Sie verschiedene Schnittstellen.(Wahrscheinlich die beste Option in meiner Meinung nach)
public interface IPAIValidateInput : IValidateInput
{
}
public interface IPPDCValidateInput : IValidateInput
{
}
Und dann registrieren sie separat in Ihrem Container und injizieren Sie die Schnittstelle, die Sie eigentlich wollen.
public TransitReport (IPAIValidateInput inputValidation,
ITransitRepository transitRepo)
{
_inputValidation = inputValidation;
_transitRepo = transitRepo;
}
Erfordert Schnittstellen ohne tatsächliche Deklaration. Aber es hält die DI-Logik in meiner Meinung reiner.
4. Verwenden eine Basisklasse und kombinieren sie alle.
Erste fix genannt Anmeldungen:
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");
Dann eine Basisklasse erstellen
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)
{
}
}
und eine Fabrik, um sie zu lösen:
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);
}
}
Dank der konkreten Klassen PPDCTransitReport
und PAITransitReport
können wir sicherstellen, dass die richtige Abhängigkeit inje ist der Basisklasse.
Wie die Fabrik verwenden:
Zuerst registriert es mit Unity.
container.RegisterType<ITransitReportFactory, TransitReportFactory>();
Dann spritzen Sie es in Ihre 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;
}
}
Aber ich muss sagen, dass die Fabrik selbst nicht so viel zur Lösung hinzufügen. Wenn Sie das Service Locator-Muster nicht stören, können Sie IUnityContainer
direkt zu TransitInfo
injizieren.
Entschuldigung für die Frage, aber ich bin etwas verwirrend über die Fabrik, wie übergebe ich den 'IUnityContainer' Typ und wo' Create' Methode aufrufen. – Riki
Sie hatten Recht zu fragen. Es war überhaupt nicht offensichtlich. Ich habe die Antwort angepasst. – smoksnes