Contextual Binding
Contextual Binding,上下文绑定,即根据不同的环境使用不同接口的实例。
先说下为什么要使用上下文绑定。
希望大家能学到更多的东西,多想想为什么,这点会对你产生非常大的影响。
通常我们会有这么几种需求:
1 Multiple bindings,多重绑定,用于多重的注入。
多重绑定,我们的对象其实是一组接口的集合。用代码的方式就是这样,程序员最喜欢的~~~
class Warrior
{
readonly IEnumerable<IWeapon> _weapons;
public Warrior( IEnumerable<IWeapon> weapons) {
_weapons=weapons;
}
public void Attack(string victim) {
foreach(var weapon in _weapons)
Console.WriteLine(weapon.Hit(victim));
}
}
2 Simple constrained resolution: Named bindings,简单约束,命名绑定
命名绑定:最简单也是最常用的方式,通过不同的条件进行绑定。代码就是 :
Bind<IWeapon>().To<Shuriken>().Named("Strong");
Bind<IWeapon>().To<Dagger>().Named("Weak");
实现的时候:
class WeakAttack {
readonly IWeapon _weapon;
public([Named("Weak")] IWeapon weakWeapon)
_weapon = weakWeapon;
}
public void Attack(string victim){
Console.WriteLine(_weapon.Hit(victim));
}
}
还有一种实现的方式:
kernel.Get<IWeapon>("Weak"); //服务定位,这是一种反模式
有兴趣的可以看看这篇文章:
还有几种比较难的,上代码,喜欢研究的可以深入 地址:上下文绑定
// will work just as well without this line, but it's more correct and important for IntelliSense etc.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter,
AllowMultiple = true, Inherited = true)]
public class Swimmer : ConstraintAttribute {
public bool Matches(IBindingMetadata metadata) {
return metadata.Has("CanSwim") && metadata.Get<bool>("CanSwim");
}
}
class WarriorsModule : Ninject.Modules.NinjectModule {
public override void Load() {
Bind<IWarrior>().To<Ninja>();
Bind<IWarrior>().To<Samurai>().WithMetadata("CanSwim", false);
Bind<IWarrior>().To<SpecialNinja>().WithMetadata("CanSwim", true);
}
}
class AmphibiousAttack {
public AmphibiousAttack([Swimmer]IWarrior warrior) {
Assert.IsType<SpecialNinja>(warrior);
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter,
AllowMultiple = true, Inherited = true)]
public class NonSwimmer : ConstraintAttribute {
public override bool Matches(IBindingMetadata metadata) {
return metadata.Has("CanSwim") && !metadata.Get<bool>("CanSwim");
}
}
class OnLandAttack {
public OnLandAttack([NonSwimmer]IWarrior warrior) {
Assert.IsType<Samurai>(warrior);
}
}
class JustAttack {
// Note: This will fail because we have three matching bindings.
public JustAttack(IWarrior warrior) {
}
}
Bind<IWarrior>().To<Samurai>().WhenInjectedInto(typeof(OnLandAttack)); Bind<IWarrior>().To<SpecialNinja>().WhenInjectedInto(typeof(AmphibiousAttack));
class SwimmerNeeded : Attribute{}
class ClimberNeeded : Attribute{}
class WarriorsModule : Ninject.Modules.NinjectModule {
public override void Load() {
Bind<IWarrior>().To<Ninja>();
Bind<IWarrior>().To<Samurai>().WhenClassHas<ClimberNeeded>();
Bind<IWarrior>().To<Samurai>().WhenTargetHas<ClimberNeeded>();
Bind<IWarrior>().To<SpecialNinja>().WhenMemberHas<SwimmerNeeded>();
}
}
class MultiAttack {
public MultiAttack([ClimberNeeded] IWarrior MountainWarrior) {
}
[Inject, SwimmerNeeded]
IWarrior OffShoreWarrior { get; set; }
[Inject]
IWarrior AnyOldWarrior {get;set;}
}
[ClimberNeeded]
class MountainousAttack {
[Inject, SwimmerNeeded]
IWarrior HighlandLakeSwimmer { get; set; }
[Inject]
IWarrior StandardMountainWarrior { get; set; }
}
Bind<IWarrior>().To<Samurai>().When(request => request.Target.Member.Name.StartsWith("Climbing"));
Bind<IWarrior>().To<Samurai>().When(request => request.Target.Type.Namespace.StartsWith("Samurais.Climbing"));
class ClassThatLogs {
ILog _log = LogFactory.CreateLog(typeof(ClassThatLogs));
// Sometimes one sees reflection based approaches too, which have efficiency issues
}
Bind<ILog>().ToMethod( context => LogFactory.CreateLog( context.Request.Target.Type ) );
class ClassThatLogs {
readonly ILog _log;
public ClassThatLogs(ILog log){
_log = log;
}
}

浙公网安备 33010602011771号