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;

    }

}

你可能感兴趣的:(context)