8

I am just beginning to learn about IoC and Dependency Injection. I am planning on doing a MonoTouch project and wanted to use TinyIoC but I wanted to test it out first. I'm creating a dummy credit card processing console app and I'm having trouble with how to configure TinyIoC since I have multiple implementations of my interface. This is my test app.

Interface:

public interface IPaymentProcessor
{
    void ProcessPayment(string cardNumber);
}

Two Implementations of the interface:

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

Simple stuff. Now I have a class that accepts the interface as a parameter in the constructor....

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

My console app looks like this....

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

        var creditCardProcessor = TinyIoCContainer.Current.Resolve<CreditCardProcessor>();
        creditCardProcessor.ProcessPayment("1234567890123456"); // 16 digits
    }
}

So I am trying to figure out how to tell the Resolve which implementation of the interface to pass to the constructor. If I run this code, I will always use the VisaPaymentProcessor implementation.

So how can I make TinyIoC pass the AmexPaymentProcessor implementation to the constructor rather than the VisaPaymentProcessor(which seems to be the default)?

4

3 回答 3

7

I haven't used TinyIoC myself, but I suspect you want:

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

(If you want to use Amex.)

There are various other Register overloads available, including one which takes a name to use, which may be useful when you resolve. It really depends on what you're trying to achieve, which isn't terribly clear from the question.

于 2012-05-02T21:00:55.687 回答
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 的所有实现并使用类名注册它们(-PaymentProcessor,如果类名以 PaymentProcessor 结尾)

然后我可以解决例如“AmexPaymentProcessor”

        IPaymentProcessor handler;
        if (TinyIoCContainer.Current.TryResolve("amex", out handler))
        {
            response = handler.ProcessPayment(cardNumber);
        }
于 2014-03-07T23:54:39.840 回答
2

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

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

于 2012-05-02T21:09:19.373 回答