代码之家  ›  专栏  ›  技术社区  ›  Michael Kang

是否有一种简单的方法将所有可用类型绑定到具体实例

  •  1
  • Michael Kang  · 技术社区  · 9 年前

    我有以下接口和具体实现:

    interface IFoo {
          string Name { get ;}
    }
    
    class Foo :IFoo{
         public string Name { get; set; }
    }
    
    interface IBar {
         string Name { get; }
    }
    
    class Bar : IBar {
         public string Name { get;set;}
    
         public Bar(Foo foo) {
    
         }
    }
    

    您可以看到,Bar在类构造函数中依赖于Foo。

    以下是我的绑定:

    kernel.Bind<IFoo>().ToConstant(new Foo() { Name="Foo"; });
    kernel.Bind<IBar>().To<Bar>();
    

    当我使用 kernel.Get 并请求Bar,没有错误,但Foo依赖项是的另一个实例 Foo 我最初绑定的。当我检查Bar构造函数中的Foo实例时,我希望看到Foo的名称为“Foo”,但我看到的却是Foo{name=null}。

    当我绑定到混凝土Foo时,一切都按预期工作:

    var foo = new Foo() { Name="Foo" };
    kernel.Bind<IFoo>().ToConstant(foo);
    kernel.Bind<Foo>().ToConstant(foo);
    kernel.Bind<IBar>().To<Bar>();
    
    var bar= kernel.Get<Bar>(); // works! foo has name "Foo"
    

    有没有一种方便的方法将Foo的特定实例绑定到所有可用接口和具体类型?

    例如:

    class ConcreteFoo : AbstractFoo, IFoo {
       ...
    }
    
    var foo = new Foo();
    kernel.Bind<IFoo>().ToConstant(foo);
    kernel.Bind<AbstractFoo>().ToConstant(foo);
    kernel.Bind<ConcreteFoo>().ToConstant(foo);
    

    我有一个通用框架。框架之外是客户定义的Foo和Bar。我希望客户能够灵活地在Bar构造函数中指定IFoo或Foo。如果构造函数被定义为Bar(IFoo),那么客户端可能会将其强制转换为Foo。

    1 回复  |  直到 9 年前
        1
  •  1
  •   BatteryBackupUnit    9 年前

    ninject没有提供这种功能。ninject提供的是绑定到多种类型,例如:

    Bind<IFoo,Foo>().To<Foo>().InSingletonScope();
    

    确保无论什么组合 IFoo Foo 你总是得到同样的 Foo公司 例子

    然后,有 Ninject.Extensions.Conventions 它可以查找类型(如程序集的所有类),并将它们绑定到其所有接口、所有基类型……,但只能是其中之一,而不是两者。你可以用它来实现你想要的,但这也需要你的终端上有相当多的代码……而且这是一种冒险。

    所以,在我看来,最好自己动手:

    using Ninject.Infrastructure.Language;
    
    public static void RegisterConstantAsAllTypes(IBindingRoot bindingRoot, object instance)
    {
        Type t = instance.GetType();
    
        IEnumerable<Type> typesToBind = t.GetAllBaseTypes()
            .Concat(t.GetInterfaces())
            .Except(new[] { typeof(object) });
    
        bindingRoot
            .Bind(typesToBind.ToArray())
            .ToConstant(instance);
    }
    

    举个例子,以下测试通过:

    [Fact]
    public void FactMethodName()
    {
        var kernel = new StandardKernel();
        var foo = new Foo();
        RegisterConstantAsAllTypes(kernel, foo);
    
        kernel.Get<IFoo>().Should().Be(foo);
        kernel.Get<Foo>().Should().Be(foo);
        kernel.Get<AbstractFoo>().Should().Be(foo);
    }