Ninject错误:有多个匹配的绑定可用

时间:2017-09-25 15:37:13

标签: c# design-patterns ninject

我正在搞乱Ninject和MVC以及设计partter。在我的简单应用程序中,我有一个这样的结构:

(抽象类)

  • interface ICoffee
  • 抽象类咖啡:ICoffee

(几个班级)

  • 公共课Espresso:Coffee,ICoffee
  • 公共课卡布奇诺:咖啡,ICoffee
  • 公共课晚:咖啡,ICoffee

(几个装饰者课程)

  • 公共课程牛奶:ICoffee
  • 公共课巧克力:ICoffee

装饰器类接受ICoffee类型的参数,更改一些设置然后返回它。

然后我有以下课程:

  public abstract class CoffeeStore : ICoffeeStore
{
    private readonly IProcessedOrderFactory processedOrderFactory;
    private readonly IDictionary<string, Func<ICoffee, ICoffee>> condimentsStrategies;

    public CoffeeStore(
        IProcessedOrderFactory processedOrderFactory,
        IDictionary<string, Func<ICoffee, ICoffee>> condimentsStrategies)
    {
        if (condimentsStrategies == null)
        {
            throw new ArgumentNullException(nameof(condimentsStrategies));
        }

        if (processedOrderFactory == null)
        {
            throw new ArgumentNullException(nameof(processedOrderFactory));
        }

        this.processedOrderFactory = processedOrderFactory;
        this.condimentsStrategies = condimentsStrategies;
    }

    public IProcessedOrder ProcessOrder(IOrder order)
    {
        ICoffee coffee;

        var coffeeType = order.SelectedCoffeeType;

        CoffeSizeType coffeeSize;
        Enum.TryParse(order.SelectedCoffeeSize, out coffeeSize);

        coffee = this.CreateCoffee(coffeeType, coffeeSize);

        foreach (var condimentAsString in order.SelectedCoffeeCodimentsList)
        {
            if (!this.condimentsStrategies.ContainsKey(condimentAsString))
            {
                throw new ArgumentException(condimentAsString);
            }

            //error occurs on the following line:
            coffee = this.condimentsStrategies[condimentAsString](coffee); 
        }

        var processedOrder = this.processedOrderFactory.CreateOrder(coffee);

        return processedOrder;
    }

    // abstract factory method
    protected abstract ICoffee CreateCoffee(string coffeeType, CoffeSizeType size);
}

 public class SofiaCoffeeStore : CoffeeStore
{
    private readonly IDictionary<string, Func<CoffeSizeType, ICoffee>> strategies;

    public SofiaCoffeeStore(
        IProcessedOrderFactory processedOrderFactory,
        IDictionary<string, Func<ICoffee, ICoffee>> condimentsStrategies,
        IDictionary<string, Func<CoffeSizeType, ICoffee>> strategies)
        : base(processedOrderFactory, condimentsStrategies)
    {
        if (strategies == null)
        {
            throw new ArgumentNullException(nameof(strategies));
        }

        this.strategies = strategies;
    }

    protected override ICoffee CreateCoffee(string coffeeType, CoffeSizeType size)
    {
        if (!this.strategies.ContainsKey(coffeeType))
        {
            throw new ArgumentNullException();
        }

        return this.strategies[coffeeType](size);
    }
}

ninject注册模块看起来像这样:

private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind(x => x
         .FromAssemblyContaining<ICoffee>()
         .SelectAllClasses()
         .Excluding<ICoffee>()
         .BindAllInterfaces());

        kernel.Bind(x => x
        .FromAssemblyContaining<ICoffee>()
        .SelectAllInterfaces()
        .EndingWith("Factory")
        .BindToFactory());

        kernel.Bind<ICoffee>().To<Americano>().NamedLikeFactoryMethod((ICoffeeTypeFactory f) => f.GetAmericano(default(CoffeSizeType)));
        kernel.Bind<ICoffee>().To<Cappuccino>().NamedLikeFactoryMethod((ICoffeeTypeFactory f) => f.GetCappucino(default(CoffeSizeType)));
        kernel.Bind<ICoffee>().To<Espresso>().NamedLikeFactoryMethod((ICoffeeTypeFactory f) => f.GetEspresso(default(CoffeSizeType)));
        kernel.Bind<ICoffee>().To<Latte>().NamedLikeFactoryMethod((ICoffeeTypeFactory f) => f.GetLatte(default(CoffeSizeType)));
        kernel.Bind<ICoffee>().To<Ristretto>().NamedLikeFactoryMethod((IPlovdivStoreCoffeeTypeFactory f) => f.GetRistretto(default(CoffeSizeType)));
        kernel.Bind<ICoffee>().To<Doppio>().NamedLikeFactoryMethod((ISofiaStoreCoffeeTypeFactory f) => f.GetDoppio(default(CoffeSizeType)));

        kernel.Bind<ICoffee>().To<Caramel>().NamedLikeFactoryMethod((ICondimentsFactory f) => f.GetCaramel(default(ICoffee)));
        kernel.Bind<ICoffee>().To<Chocolate>().NamedLikeFactoryMethod((ICondimentsFactory f) => f.GetChocolate(default(ICoffee)));
        kernel.Bind<ICoffee>().To<Cinnamon>().NamedLikeFactoryMethod((ICondimentsFactory f) => f.GetCinnamon(default(ICoffee)));
        kernel.Bind<ICoffee>().To<Milk>().NamedLikeFactoryMethod((ICondimentsFactory f) => f.GetMilk(default(ICoffee)));
        kernel.Bind<ICoffee>().To<WhippedCream>().NamedLikeFactoryMethod((ICondimentsFactory f) => f.GetWhippedCream(default(ICoffee)));

        var sofiaStoreStrategies = new Dictionary<string, Func<CoffeSizeType, ICoffee>>
        {
            { "Americano", kernel.Get<ICoffeeTypeFactory>().GetAmericano },
            { "Capuccino", kernel.Get<ICoffeeTypeFactory>().GetCappucino },
            { "Espresso", kernel.Get<ICoffeeTypeFactory>().GetEspresso },
            { "Latte", kernel.Get<ICoffeeTypeFactory>().GetLatte },
            { "Doppio", kernel.Get<ISofiaStoreCoffeeTypeFactory>().GetDoppio },
        };

        var plovdivStoreStrategies = new Dictionary<string, Func<CoffeSizeType, ICoffee>>
        {
            { "Americano", kernel.Get<ICoffeeTypeFactory>().GetAmericano },
            { "Capuccino", kernel.Get<ICoffeeTypeFactory>().GetCappucino },
            { "Espresso", kernel.Get<ICoffeeTypeFactory>().GetEspresso },
            { "Latte", kernel.Get<ICoffeeTypeFactory>().GetLatte },
            { "Ristretto", kernel.Get<IPlovdivStoreCoffeeTypeFactory>().GetRistretto },
        };

        var condimentsStrategies = new Dictionary<string, Func<ICoffee, ICoffee>>
        {
            { "Milk", kernel.Get<ICondimentsFactory>().GetMilk },
            { "Caramel", kernel.Get<ICondimentsFactory>().GetCaramel },
            { "Chocolate", kernel.Get<ICondimentsFactory>().GetChocolate },
            { "Cinnamon", kernel.Get<ICondimentsFactory>().GetCinnamon },
            { "Whipped cream", kernel.Get<ICondimentsFactory>().GetWhippedCream },
        };


        kernel.Bind<IDictionary<string, Func<CoffeSizeType, ICoffee>>>().ToConstant(sofiaStoreStrategies)
            .WhenInjectedInto<SofiaCoffeeStore>();
        kernel.Bind<IDictionary<string, Func<CoffeSizeType, ICoffee>>>().ToConstant(plovdivStoreStrategies)
            .WhenInjectedInto<PlovdivCoffeeStore>();
        kernel.Bind<IDictionary<string, Func<ICoffee, ICoffee>>>().ToConstant(condimentsStrategies)
                .WhenInjectedInto<CoffeeStore>();

       //some more bellow
    }

ProcessOrder方法(CoffeeStore类)发生错误。

Ninject.ActivationException occurred
HResult=0x80131500
Message=Error activating ICoffee
More than one matching bindings are available.
Matching bindings:
1) binding from ICoffee to Caramel
2) binding from ICoffee to Chocolate
3) binding from ICoffee to Cinnamon
 .....
22) binding from ICoffee to WhippedCream
Activation path:
2) Injection of dependency ICoffee into parameter coffee of constructor of type Cinnamon
1) Request for ICoffee
Suggestions:
1) Ensure that you have defined a binding for ICoffee only once.

我从3阶段向导表单中收集用户输入为字符串,然后立即使用它进行对象初始化。希望我分享的代码足以让我知道接下来要做的事情: 首先,我想初始化一个咖啡类型类,然后用一个或多个装饰器类来装饰对象。 第二步发生错误 - 当我尝试初始化装饰器类时,第一步就可以了。知道怎么克服这个吗?

0 个答案:

没有答案