C# TinyIoC-接口的多个实现

C# TinyIoC-接口的多个实现,c#,dependency-injection,tinyioc,C#,Dependency Injection,Tinyioc,我刚刚开始了解IoC和依赖注入。我计划做一个MonoTouch项目,想使用TinyIoC,但我想先测试一下。我正在创建一个虚拟的信用卡处理控制台应用程序,我在配置TinyIoC时遇到了问题,因为我有多个接口实现。这是我的测试应用程序 接口: public interface IPaymentProcessor { void ProcessPayment(string cardNumber); } 接口的两种实现方式: VisaPaymentProcessor public class

我刚刚开始了解IoC和依赖注入。我计划做一个MonoTouch项目,想使用TinyIoC,但我想先测试一下。我正在创建一个虚拟的信用卡处理控制台应用程序,我在配置TinyIoC时遇到了问题,因为我有多个接口实现。这是我的测试应用程序

接口

public interface IPaymentProcessor
{
    void ProcessPayment(string cardNumber);
}
接口的两种实现方式:

VisaPaymentProcessor

public class VisaPaymentProcessor : IPaymentProcessor
{
    public void ProcessPayment(string cardNumber)
    {
        if (cardNumber.Length != 13 && cardNumber.Length != 16)
        {
            new ArgumentException("Card Number isn't the correct length");
        }

        // some code for processing payment
    }
}
public class AmexPaymentProcessor : IPaymentProcessor
{
    public void ProcessPayment(string cardNumber)
    {
        if (cardNumber.Length != 15)
        {
            new ArgumentException("Card Number isn't the correct length");
        }

        // some code for processing the payment
    }
}
public class CreditCardProcessor
{
    public IPaymentProcessor PaymentProcessor { get; set; }

    public CreditCardProcessor(IPaymentProcessor processor)
    {
        this.PaymentProcessor = processor;
    }

    public void ProcessPayment(string creditCardNumber)
    {
        this.PaymentProcessor.ProcessPayment(creditCardNumber);
    }
}
AmexPaymentProcessor

public class VisaPaymentProcessor : IPaymentProcessor
{
    public void ProcessPayment(string cardNumber)
    {
        if (cardNumber.Length != 13 && cardNumber.Length != 16)
        {
            new ArgumentException("Card Number isn't the correct length");
        }

        // some code for processing payment
    }
}
public class AmexPaymentProcessor : IPaymentProcessor
{
    public void ProcessPayment(string cardNumber)
    {
        if (cardNumber.Length != 15)
        {
            new ArgumentException("Card Number isn't the correct length");
        }

        // some code for processing the payment
    }
}
public class CreditCardProcessor
{
    public IPaymentProcessor PaymentProcessor { get; set; }

    public CreditCardProcessor(IPaymentProcessor processor)
    {
        this.PaymentProcessor = processor;
    }

    public void ProcessPayment(string creditCardNumber)
    {
        this.PaymentProcessor.ProcessPayment(creditCardNumber);
    }
}
简单的东西。现在我有了一个类,它接受接口作为构造函数中的参数

CreditCardProcessor

public class VisaPaymentProcessor : IPaymentProcessor
{
    public void ProcessPayment(string cardNumber)
    {
        if (cardNumber.Length != 13 && cardNumber.Length != 16)
        {
            new ArgumentException("Card Number isn't the correct length");
        }

        // some code for processing payment
    }
}
public class AmexPaymentProcessor : IPaymentProcessor
{
    public void ProcessPayment(string cardNumber)
    {
        if (cardNumber.Length != 15)
        {
            new ArgumentException("Card Number isn't the correct length");
        }

        // some code for processing the payment
    }
}
public class CreditCardProcessor
{
    public IPaymentProcessor PaymentProcessor { get; set; }

    public CreditCardProcessor(IPaymentProcessor processor)
    {
        this.PaymentProcessor = processor;
    }

    public void ProcessPayment(string creditCardNumber)
    {
        this.PaymentProcessor.ProcessPayment(creditCardNumber);
    }
}
我的控制台应用程序看起来像这样

class Program
{
    static void Main(string[] args)
    {
        TinyIoCContainer.Current.AutoRegister();

        var creditCardProcessor = TinyIoCContainer.Current.Resolve<CreditCardProcessor>();
        creditCardProcessor.ProcessPayment("1234567890123456"); // 16 digits
    }
}
类程序
{
静态void Main(字符串[]参数)
{
TinyIoCContainer.Current.AutoRegister();
var creditCardProcessor=TinyIoCContainer.Current.Resolve();
creditCardProcessor.ProcessPayment(“12345678901233456”);//16位
}
}
因此,我试图找出如何告诉
解析
将哪个接口实现传递给构造函数。如果我运行此代码,我将始终使用
VisaPaymentProcessor
实现


那么,如何让TinyIoC将
AmexPaymentProcessor
实现传递给构造函数,而不是
VisaPaymentProcessor
(这似乎是默认值)?

我自己没有使用TinyIoC,但我怀疑您想要:

TinyIoCContainer.Current.Register(typeof(IPaymentProcessor),
                                  typeof(AmexPaymentProcessor));
(如果您想使用美国运通。)


还有其他各种可用的
Register
重载,包括一个使用名称的重载,在解析时可能很有用。这实际上取决于你想要实现什么,这一点从问题上看还不是很清楚。

我不太确定你在这里想要实现什么,但是如果你有一个接口的多个实现,并且你想要一个特定的实现,那么你需要用一个名称注册每个实现,或者使用RegisterMultiple,使用类型名称作为名称,然后使用该名称解析,并将其与NamedParameters重载一起使用,以指定所需的名称


听起来更像是您可能需要某种ProcessorFactory或某种facade,它依赖于IEnumerable,并根据传入的数字提供/充当正确实现的facade。

类似于Global.asax或应用程序条目中的内容(针对您的示例进行了修改)

它查找IPaymentProcessor的所有实现,并使用classname注册它们 (-PaymentProcessor,如果类名以PaymentProcessor结尾)

然后我可以用


谢谢我用这个问题更新了帖子。似乎
VisaPaymentProcessor
是TinyIoC使用的“默认”实现。如何让TinyIoC将
AmexPaymentProcessor
实现传递给构造函数。很抱歉说不清楚。@Eclipsed4utoo:好的-在这种情况下,我希望我的答案能涵盖它:)@JonSkeet为我的理解不足道歉,但这如何解决OPs最初的问题呢?看起来他们希望能够在运行时有条件地解析已注册的依赖项。@Tom:我看不出问题中有任何关于在执行时确定依赖项的内容。@JonSkeet他们不是这样问的,所以我试图找出如何告诉解析传递给建造师?本例中的构造函数是
public CreditCardProcessor(IPaymentProcessor)
我读过关于温莎IoC的文章,想知道TinyIoC是否也是如此<代码>现在,当您“解析”CreditCardProcessor的实例时,容器会查看构造函数并发现它需要一个IPaymentProcessor。容器查看该类型是否已在容器中注册。如果是,容器将“解析”该类型,然后实例化CreditCardProcessor。如果是,当有两个实现注册到接口时,TinyIoC如何处理?使用
RegisterMultiple
@eclipsed4uto时,它似乎选择了第一个注册的类型。一个接口只有一个“默认”注册(一个没有名称的注册),如果您依赖它,就会得到这个注册。当你使用AutoRegister时,不能保证哪一个是“默认”的,所以你应该自己设置,或者全部注册,然后按名称取出正确的。谢谢Steven。我能找到的指定正确实现的唯一方法是在解析
CreditCardProcessor
时使用NamedParameterOverloads。然而,这似乎“硬编码”了构造函数的签名,因为我需要NamedParametersOverload来匹配构造函数签名。如果构造函数发生更改,那么如果我不在那里进行更改,NamedParametersOverload现在将失败。对我来说,这样做违背了使用国际奥委会的目的。我是不是离基地太远了?