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

本文关键字:绑定 类型 实例 一个 简单 一种 方法 有没有 | 更新日期: 2023-09-27 18:29:04

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

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。

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

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

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

确保无论请求IFooFoo的组合是什么,都始终获得相同的Foo实例。

然后,还有Ninject.Extensions.Conferences,它可以查找类型(像程序集的所有类),并将它们绑定到所有接口、所有基类型,。。。但只能选择其中之一,而不能同时选择两者。你可以使用它来实现你想要的,但这也需要你端的一些代码,。。这会有点古怪。

所以,在我看来,最好只推出自己的:

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);
}