Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/267.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 这是否正确使用依赖项注入?_C#_Dependency Injection - Fatal编程技术网

C# 这是否正确使用依赖项注入?

C# 这是否正确使用依赖项注入?,c#,dependency-injection,C#,Dependency Injection,我有一个从存储库检索DTO的服务层。根据DTO中的属性,我需要使用两种策略中的一种来对DTO执行计算。我创建了一个工厂来返回适当的策略,并使用DI容器()来实例化对象 public class CalculationFactory { private readonly IDependencyResolver _resolver; public CalculationFactory(IDependencyResolver resolver) { ThrowI

我有一个从存储库检索DTO的服务层。根据DTO中的属性,我需要使用两种策略中的一种来对DTO执行计算。我创建了一个工厂来返回适当的策略,并使用DI容器()来实例化对象

public class CalculationFactory
{
    private readonly IDependencyResolver _resolver;
    public CalculationFactory(IDependencyResolver resolver)
    {
        ThrowIfNullArgument(resolver, "resolver", typeof(IDependencyResolver));
        _resolver = resolver;
    }

    public static ICalculation CreateCalculator(int serviceType)
    {
        switch (serviceType)
        {
            case 1: return _resolver.Resolve<ICalculation>("Type1");
            case 2: return _resolver.Resolve<ICalculation>("Type2");
            default: return _resolver.Resolve<ICalculation>("InvalidType");
        }
    }
}
但在我的容器中,我可以注册不同的计算器,如果我作为混凝土工厂通过容器,我会得到如下内容(未测试),坦白地说,这对我来说是相当合理的。欢迎提供任何反馈/澄清

Container.Register<IChargeCalculator>("Actuals",
                                      c => new ActualsChargeCalculator());
Container.Register<IChargeCalculator>("CopyBlock",
                                      c => new CopyBlockChargeCalculator());
...
public enum ServiceType
{
    Actuals = 1, CopyBlock,
}

public interface IChargeCalculator
{
    decimal CalculateCharge();
}

public class MeterReading
{
    private readonly IDependencyResolver chargeCalculatorFactory;
    private ServiceType serviceType;
    public MeterReading(IDependencyResolver chargeCalculatorFactory)
    {
        if (chargeCalculatorFactory == null)
            throw new ArgumentNullException("chargeCalculatorFactory");
        this.chargeCalculatorFactory = chargeCalculatorFactory;    
    }

    public decimal Charge
    {
        get
        {
            return chargeCalculatorFactory.Resolve<IChargeCalculator>(serviceType.ToString());
        }
    }
}
Container.Register(“实际值”,
c=>new ActualChargeCalculator());
Container.Register(“CopyBlock”,
c=>新的CopyBlockChargeCalculator());
...
公共枚举服务类型
{
实际值=1,复制块,
}
公共接口计算机
{
十进制计算器charge();
}
公共类仪表读数
{
专用只读IDependencyResolver chargeCalculatorFactory;
私有服务类型服务类型;
公用电表读数(iDependency分解器充电器计算器工厂)
{
如果(chargeCalculatorFactory==null)
抛出新ArgumentNullException(“chargeCalculatorFactory”);
this.chargeCalculatorFactory=chargeCalculatorFactory;
}
公共十进制收费
{
得到
{
返回chargeCalculatorFactory.Resolve(serviceType.ToString());
}
}
}

我相信这个问题已经在这里得到了回答,这里建议您对绑定使用元数据,并为每个实现创建绑定。然后使用绑定拉取元数据以选择要使用的绑定:。这在Munq中可能实现,也可能不实现?不确定


回答这个问题的人(Remo)是ninject的设计师之一,他学识渊博。我认为他的回答应该很有分量。(我是ninject邮件列表的订阅者,看到他回答了大约一半的问题,这是一个很好的例子)。

是的,我想说你做得很好

尽管您编写了需要“传入依赖项解析器”的代码,但有没有理由不能将工厂类注入到需要它的类中?然后,Factory对依赖项解析程序的依赖项应由依赖项解析程序本身(对自身)解析

我希望那句话有意义

我试图想出一个“更清洁”的解决方案,但还没有找到。一个类似于问题中建议的解决方案(不完全相同)Dessus链接当然是可能的,但我真的认为这只是将相同的代码移动到另一个地方。Remo还写道,它可以在工厂类而不是工厂方法中完成

这有点像是在编写lampda或helper类之间做出选择。它主要归结为可读性,对我来说,工厂方法太大了,在模块初始化器或引导程序中使用它会导致混乱


顺便说一句,我可以推荐Ninject,它是一款非常好、干净的DI。另外,它的文档使用了忍者示例;)

我支持Ninject的建议。不过要小心盗版。你能给我一个注入工厂类的例子吗?如果我注入工厂,我如何在不破坏对象图的情况下解析Create方法中的计算,即如果计算需要解析其他对象。我不能随便换个合适的对象。这有意义吗?感谢您对Ninject的推荐,到目前为止,我对Munq很满意-它相对轻便且快速。请注意,您在这里解决依赖关系的方式通常被称为“服务定位器”模式(或反模式,取决于您的观点):我通常会尽量避免使用服务定位器模式,但有时这是不可避免的。感谢rally25rs,我看了Mark的帖子,但它没有提供一种从Service Locator重构到更好的方式。以下是方法:
Container.Register<IChargeCalculator>("Actuals",
                                      c => new ActualsChargeCalculator());
Container.Register<IChargeCalculator>("CopyBlock",
                                      c => new CopyBlockChargeCalculator());
...
public enum ServiceType
{
    Actuals = 1, CopyBlock,
}

public interface IChargeCalculator
{
    decimal CalculateCharge();
}

public class MeterReading
{
    private readonly IDependencyResolver chargeCalculatorFactory;
    private ServiceType serviceType;
    public MeterReading(IDependencyResolver chargeCalculatorFactory)
    {
        if (chargeCalculatorFactory == null)
            throw new ArgumentNullException("chargeCalculatorFactory");
        this.chargeCalculatorFactory = chargeCalculatorFactory;    
    }

    public decimal Charge
    {
        get
        {
            return chargeCalculatorFactory.Resolve<IChargeCalculator>(serviceType.ToString());
        }
    }
}