注入需求对象取决于构造函数注入中的条件

力木

我有一个界面

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

烟雾

有几种方法。

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

多亏了具体的类PPDCTransitReportPAITransitReport我们可以确保将正确的依赖项注入到基类中。

如何使用工厂:

首先,向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] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

注入需求对象取决于构造函数注入中的条件

来自分类Dev

注入值取决于要注入的对象

来自分类Dev

Restler中的构造函数注入

来自分类Dev

构造函数中的依赖注入

来自分类Dev

Angular 2依赖注入-独立于构造函数注入对象

来自分类Dev

如何使用构造函数注入创建对象?

来自分类Dev

帅哥 注入构造函数

来自分类Dev

春季构造函数注入

来自分类Dev

Java构造函数注入

来自分类Dev

在注入构造函数之前注入成员变量

来自分类Dev

在测试的类中没有可用的可注入对象可以满足的构造函数

来自分类Dev

如何在构造函数中使用注入的对象?

来自分类Dev

Unity在app.config中注入复杂的构造函数对象

来自分类Dev

通过生成构造函数将超类注入原始对象

来自分类Dev

使用 Guice 将特定对象注入特定构造函数

来自分类Dev

动态注入构造函数参数

来自分类Dev

在构造函数上注入属性

来自分类Dev

构造函数路径参数的注入

来自分类Dev

构造函数注入最佳实践

来自分类Dev

构造函数注入Dagger 2

来自分类Dev

对Xsockets构造函数的依赖注入

来自分类Dev

带参数的构造函数注入

来自分类Dev

注入类的构造函数参数

来自分类Dev

动态注入构造函数参数

来自分类Dev

构造函数注入vs IocFactory

来自分类Dev

构造函数注入Dagger 2

来自分类Dev

将 ChangeTracker 注入构造函数

来自分类Dev

使用需求将对象注入Ember.js中的其他对象

来自分类Dev

简单注入器:取决于http请求的实现