TinyIoC - 接口的多种实现

时间:2012-05-02 20:50:41

标签: c# dependency-injection tinyioc

我刚刚开始了解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
    }
}

AmexPaymentProcessor

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

简单的东西。现在我有一个类接受接口作为构造函数中的参数....

CreditCardProcessor

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

所以我试图找出如何告诉Resolve接口的哪个实现传递给构造函数。如果我运行此代码,我将始终使用VisaPaymentProcessor实现。

那么我怎样才能让TinyIoC将AmexPaymentProcessor实现传递给构造函数而不是VisaPaymentProcessor(这似乎是默认的)?

3 个答案:

答案 0 :(得分:7)

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

TinyIoCContainer.Current.Register(typeof(IPaymentProcessor),
                                  typeof(AmexPaymentProcessor));

(如果你想使用美国运通卡。)

还有其他各种Register重载可供使用,包括一个使用名称的重载,这在您解决时可能很有用。这实际上取决于你想要达到的目标,这个问题并不十分清楚。

答案 1 :(得分:2)

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

听起来你可能想要某种ProcessorFactory或某种类型的外观,它依赖于IEnumerable,并根据传入的数量提供/充当正确实现的外观。

答案 2 :(得分:2)

Global.asax或应用程序条目中的类似内容(为您的示例修改)

        const string nameTrim = "paymentprocessor"; 
        var type = typeof(IPaymentProcessor);
        AppDomain.CurrentDomain.GetAssemblies()
            .SelectMany(s => s.GetTypes())
            .Where(x => type.IsAssignableFrom(x) && x.IsClass).ToList()
            .ForEach(t =>
            {
                var name = t.Name.ToLower();
                if (name.EndsWith(nameTrim))
                    name = name.Substring(0, name.Length - nameTrim.Length);

                TinyIoCContainer.Current.Register(type, t, name);
            });

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

然后我可以用

解析例如“AmexPaymentProcessor”
        IPaymentProcessor handler;
        if (TinyIoCContainer.Current.TryResolve("amex", out handler))
        {
            response = handler.ProcessPayment(cardNumber);
        }