Ninject默认语境结合 [英] Ninject default contextual binding
问题描述
我有一些不同的具体实现的接口。我想给Ninject默认使用且仅当名称匹配使用其他实现。 。比如,我有以下的绑定
绑定< ISomething>()为<。DefaultSomething>()
绑定&所述; ISomething方式>()到< OtherSomething方式>()命名(55abd8b8-097f-4e1c-8d32-95cc97910604);
我想是,如果命名节不匹配,使用DefaultSomething实现。当我通过在明确的约束GUID,它工作正常。当我通过任何其他GUID我得到了无匹配的绑定可用异常
绑定< ISomething>()。到< OtherSomething方式>()命名(55abd8b8-097f-4e1c-8d32-95cc97910604);
绑定&所述; ISomething方式>()到< DefaultSomething>()
绑定&所述; ISomething方式>()到< DefaultSomething>()
绑定&所述; ISomething方式>()至< ; OtherSomething方式>()时(CTX = GT; ctx.Service =空&放大器;!&放大器; ctx.Service.Name ==55abd8b8-097f-4e1c-8d32-95cc97910604);
我使用。当检查还试图绑定,我试图扭转的顺序如下图所示然而,我从来没有能够绑定,除非我通过在被明确指定的GUID。
的This文章似乎表明,默认绑定工作,所以我必须做一些错误的。 ?任何建议
编辑:这是显示我试图解决这个问题一个完整的例子。期望的行为是 kernel.Get< i编号方式>(三公)写()
返回未知号码
使用系统;
使用System.Collections.Generic;
使用System.Linq的;
使用System.Text;
使用Ninject;
命名空间NinjectTest
{
接口i编号
{
串写();
}
类UnknownNumber:i编号
{
公共字符串写入()
{
返回未知号码;
}
}
类中的一个:i编号
{
公共字符串写入()
{
返回1 =一
}
}
类两种:i编号
{
公共字符串写入()
{
返回2 = 2
}
}
类节目
{
静态无效的主要(字串[] args)
{
StandardKernel内核=新StandardKernel();
kernel.Bind&所述; i编号方式>()到< UnknownNumber>();
kernel.Bind< i编号方式>()为<一种方式>()命名(1);
kernel.Bind< i编号方式>()到<二方式>()命名(二);
Console.WriteLine(kernel.Get< i编号>(1)写());
Console.WriteLine(kernel.Get< i编号>(二),写());
Console.WriteLine(kernel.Get< i编号>(三公)写());
到Console.ReadLine();
}
}
}
您完全missunderstood命名的绑定:
给人一种绑定的名称不是一个条件。没有约束,要求他们时,你仍然会得到所有的人。添加一个名称更改对自己绝对没有
请求使用一个名称的一个实例添加了约束:
只有绑定的名字相匹配的给定的一个应退还
块引用>
在你的情况,你给我一个实例其绑定的名称是
三化
。你希望它返回UnknownNumber
,它甚至没有一个名字。
这可以通过<实现STRONG>或者
- 传递参数和添加条件的检查,如果参数匹配,或绑定
- 通过适合的名称或命名的实体并声明未命名的隐式。
$ b约束$ b选项1:
公共类CustomerIdParameter:参数
{
公共CustomerIdParameter(串ID):基地(客户编号(对象)空,假)
{
this.Id = ID;
}
公共字符串ID {搞定;私人集; }
}
kernel.Bind< ISomething>()到<&默认GT;();
kernel.Bind&所述; ISomething方式>()向<其它>()
。当(R => r.Parameters.OfType&下; CustomerIdParameter>()
。单()的标识。 ==SomeName);
kernel.Get< IWeapon>(新CustomerIdParameter(SomeName))ShouldBeInstanceOf<剑与GT;();
我把它留给你写的扩展方法做出的定义和解决更容易。
选项2:
绑定< ISomething>()为<默认过夜。 ()Binding.IsImplicit = TRUE。
绑定< ISomething方式>()为<其他方式>()命名(SomeName)
公共静态牛逼GetNamedOrDefault< T>(此的iKernel内核,字符串名称)
{
返回kernel.Get< T>(M = GT; m.Name == NULL || m.Name ==名);
}
不过说实话,我认为你想做的事似乎并没有成为一个什么恰当的设计:
- 保持绝对最低内核的访问。你在做什么这里是一个的ServiceLocator类 Ninject的使用。
- 如果没有绑定可预期的情况下,我宁愿期待一个例外比使用默认实例,因为这是一个错误。
I have an interface with a few different concrete implementations. I am trying to give Ninject a default to use and only use the other implementation if a name matches. For instance, I have the following bindings.
Bind<ISomething>().To<DefaultSomething>() Bind<ISomething>().To<OtherSomething>().Named("55abd8b8-097f-4e1c-8d32-95cc97910604");
What I would like is if the Named section doesn't match, to use the DefaultSomething implementation. When I pass in the explicitly bound guid, it works fine. When I pass in any other guid I get the "No matching bindings are available" exception.
Bind<ISomething>().To<OtherSomething>().Named("55abd8b8-097f-4e1c-8d32-95cc97910604"); Bind<ISomething>().To<DefaultSomething>() Bind<ISomething>().To<DefaultSomething>() Bind<ISomething>().To<OtherSomething>().When(ctx => ctx.Service != null && ctx.Service.Name == "55abd8b8-097f-4e1c-8d32-95cc97910604");
I have also tried using .When to check the binding and I have tried reversing the order like below however I am never able to bind unless I pass in the Guid that is explicitly named.
This article seems to indicate that default bindings work, so I must be doing something wrong. Any suggestions?
Edit: Here is a complete example showing the problem I am trying to solve. The desired behavior is for
kernel.Get<INumber>("Three").Write()
to return"Unknown Number"
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Ninject; namespace NinjectTest { interface INumber { string Write(); } class UnknownNumber : INumber { public string Write() { return "Unknown Number"; } } class One : INumber { public string Write() { return "1 = One"; } } class Two : INumber { public string Write() { return "2 = Two"; } } class Program { static void Main(string[] args) { StandardKernel kernel = new StandardKernel(); kernel.Bind<INumber>().To<UnknownNumber>(); kernel.Bind<INumber>().To<One>().Named("One"); kernel.Bind<INumber>().To<Two>().Named("Two"); Console.WriteLine(kernel.Get<INumber>("One").Write()); Console.WriteLine(kernel.Get<INumber>("Two").Write()); Console.WriteLine(kernel.Get<INumber>("Three").Write()); Console.ReadLine(); } } }
解决方案You completely missunderstood named bindings:
Giving a binding a name is NOT a condition. You will still get all of them when requesting them without a constraint. Adding a name changes absolutely nothing on its own.
Requesting an instance using a name adds the constraint:
only bindings whose name matches the given one shall be returned
In your case, you gave me an instance whose binding's name is
"three"
. And you expect it to returnUnknownNumber
, which does not even have a name.This can be achieved by either
- passing a parameter and adding conditions to the bindings that check if the parameter matches, or
- passing a constraint that fits the name or the unnamed instance and declare the unnamed one implicit.
Option 1:
public class CustomerIdParameter : Parameter { public CustomerIdParameter(string id) : base("CustomerId", (object)null, false) { this.Id = id; } public string Id { get; private set; } } kernel.Bind<ISomething>().To<Default>(); kernel.Bind<ISomething>().To<Other>() .When(r => r.Parameters.OfType<CustomerIdParameter>() .Single().Id == "SomeName"); kernel.Get<IWeapon>(new CustomerIdParameter("SomeName")).ShouldBeInstanceOf<Sword>();
I leave it up to you to write the extension methods to make the definition and resolve easier.
Option 2:
Bind<ISomething>().To<Default>().Binding.IsImplicit = true; Bind<ISomething>().To<Other>().Named("SomeName") public static T GetNamedOrDefault<T>(this IKernel kernel, string name) { return kernel.Get<T>(m => m.Name == null || m.Name == name); }
But honestly I think what you want to do doesn't seem to be a proper design:
- Keep your access to the kernel to an absolute minimum. What you're doing here is a ServiceLocator-like usage of Ninject.
- If no binding is available for an expected instance, I'd rather expect an exception than using a default instance because this is a bug.
这篇关于Ninject默认语境结合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!