简体   繁体   English

TinyIoC - 接口的多种实现

[英]TinyIoC - Multiple Implementations of Interface

I am just beginning to learn about IoC and Dependency Injection. 我刚刚开始学习IoC和依赖注入。 I am planning on doing a MonoTouch project and wanted to use TinyIoC but I wanted to test it out first. 我打算做一个MonoTouch项目,想要使用TinyIoC,但我想先测试一下。 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. 我正在创建一个虚拟信用卡处理控制台应用程序,我遇到了如何配置TinyIoC的问题,因为我有多个接口实现。 This is my test app. 这是我的测试应用。

Interface : 界面

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

Two Implementations of the interface: 界面的两个实现:

VisaPaymentProcessor 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 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 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. 所以我试图弄清楚如何告诉Resolve接口的哪个实现传递给构造函数。 If I run this code, I will always use the VisaPaymentProcessor implementation. 如果我运行此代码,我将始终使用VisaPaymentProcessor实现。

So how can I make TinyIoC pass the AmexPaymentProcessor implementation to the constructor rather than the VisaPaymentProcessor (which seems to be the default)? 那么如何让TinyIoC将AmexPaymentProcessor实现传递给构造函数而不是VisaPaymentProcessor (这似乎是默认的)?

I haven't used TinyIoC myself, but I suspect you want: 我自己没有使用过TinyIoC,但我怀疑你想要:

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. 还有其他各种可用的Register重载,包括一个使用名称的重载,这在您解决时可能很有用。 It really depends on what you're trying to achieve, which isn't terribly clear from the question. 这实际上取决于你想要达到的目标,这个问题并不十分清楚。

I'm not really sure what you're trying to achieve here, but if you have multiple implementations of an interface and you want a specific one then you need to register each one with a name, or use RegisterMultiple, which uses the type name for a name, then resolve using that name and use that along with NamedParameterOverloads to specify which one you want. 我不确定你要在这里实现什么,但是如果你有多个接口实现而你想要一个特定的接口,那么你需要用名称注册每个接口,或者使用RegisterMultiple,它使用类型名称对于名称,然后使用该名称解析并与NamedParameterOverloads一起使用以指定您想要的名称。

It sounds more like though that you might want some kind of ProcessorFactory, or a facade of some kind, that takes a dependency on IEnumerable and supplies/acts as a facade for the correct implementation depending on the number passed in. 这听起来更像是你可能想要某种ProcessorFactory,或某种类型的外观,它依赖于IEnumerable,并根据传入的数量提供/充当正确实现的外观。

Something like this in Global.asax or application entry (Modified for your example) 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);
            });

It finds alla implementations of IPaymentProcessor and registers them with classname (-PaymentProcessor, if the classname ends with PaymentProcessor) 它找到了IPaymentProcessor的alla实现,并使用classname注册它们(-PaymentProcessor,如果类名以PaymentProcessor结尾)

Then I can resolve for example "AmexPaymentProcessor" with 然后我可以解决例如“AmexPaymentProcessor”的问题

        IPaymentProcessor handler;
        if (TinyIoCContainer.Current.TryResolve("amex", out handler))
        {
            response = handler.ProcessPayment(cardNumber);
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM