我正在搞乱Ninject和MVC以及设计partter。在我的简单应用程序中,我有一个这样的结构:
(抽象类)
(几个班级)
(几个装饰者课程)
装饰器类接受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阶段向导表单中收集用户输入为字符串,然后立即使用它进行对象初始化。希望我分享的代码足以让我知道接下来要做的事情: 首先,我想初始化一个咖啡类型类,然后用一个或多个装饰器类来装饰对象。 第二步发生错误 - 当我尝试初始化装饰器类时,第一步就可以了。知道怎么克服这个吗?