C# Ninject.Extensions.Conventions在接口和基类的绑定列表中注入单例

C# Ninject.Extensions.Conventions在接口和基类的绑定列表中注入单例,c#,binding,singleton,ninject,C#,Binding,Singleton,Ninject,我得到了以下将失败的测试用例: 预期:与ArxScriptsTests.Engines.Ioc.Examples+A相同,但为: ArxScriptsTests.Engines.Ioc.Examples+A 问题是,如何使它正确 [TestFixture] public class Examples { public interface IInterface { } public abstract class BaseClass : IInterface

我得到了以下将失败的测试用例:

预期:与ArxScriptsTests.Engines.Ioc.Examples+A相同,但为: ArxScriptsTests.Engines.Ioc.Examples+A

问题是,如何使它正确

[TestFixture]
public class Examples
{
    public interface IInterface
    {

    }

    public abstract class BaseClass : IInterface
    {

    }

    public class A : BaseClass
    {

    }

    public class B : BaseClass
    {

    }


    [Test]
    public void TestMethod1()
    {
        IKernel kernel = new StandardKernel();

        // Bind to self
        kernel.Bind(x => x
            .FromThisAssembly()
            .SelectAllClasses().InheritedFrom<BaseClass>()
            .BindToSelf()
            .Configure(b => b.InSingletonScope())
            );

        // Bind to IInterface
        kernel.Bind(x => x
            .FromThisAssembly()
            .SelectAllClasses().InheritedFrom<IInterface>()
            .BindSelection((type, baseTypes) => new List<Type> { typeof(IInterface) })
            .Configure(b => b.InSingletonScope())
            );


        // Bind to BaseClass
        kernel.Bind(x => x
            .FromThisAssembly()
            .SelectAllClasses().InheritedFrom<BaseClass>()
            .BindSelection((type, baseTypes) => new List<Type> { typeof(BaseClass) })
            .Configure(b => b.InSingletonScope())
            );




        List<IInterface> byInterface = new List<IInterface>(kernel.GetAll<IInterface>());
        List<BaseClass> byBaseClass = new List<BaseClass>(kernel.GetAll<BaseClass>());


        Assert.AreSame(byInterface[0], byBaseClass[0]);
    }
}
[TestFixture]
公开课示例
{
公共接口接口
{
}
公共抽象类基类:IInterface
{
}
公共A类:基本类
{
}
公共类B:基本类
{
}
[测试]
公共void TestMethod1()
{
IKernel kernel=新的标准内核();
//约束自己
Bind(x=>x
.FromThisAssembly()中的
.SelectAllClasses().InheritedFrom()
.BindToSelf()
.Configure(b=>b.InSingletonScope())
);
//绑定到接口
Bind(x=>x
.FromThisAssembly()中的
.SelectAllClasses().InheritedFrom()
.BindSelection((type,baseTypes)=>新列表{typeof(IInterface)})
.Configure(b=>b.InSingletonScope())
);
//绑定到基类
Bind(x=>x
.FromThisAssembly()中的
.SelectAllClasses().InheritedFrom()
.BindSelection((type,baseTypes)=>新列表{typeof(BaseClass)})
.Configure(b=>b.InSingletonScope())
);
List byInterface=新列表(kernel.GetAll());
List byBaseClass=新列表(kernel.GetAll());
AreName(byInterface[0],byBaseClass[0]);
}
}
一种解决方案是

[Test]
public void TestMethod1()
{
    IKernel kernel = new StandardKernel();

    // Bind to Both
    kernel.Bind(x => x
        .FromThisAssembly()
        .SelectAllClasses().InheritedFrom<IInterface>()
        .BindSelection((type, baseTypes) => new List<Type> { typeof(IInterface), typeof(BaseClass) })
        .Configure(b => b.InSingletonScope())
        );


    List<IInterface> byInterface = new List<IInterface>(kernel.GetAll<IInterface>());
    List<BaseClass> byBaseClass = new List<BaseClass>(kernel.GetAll<BaseClass>());


    Assert.AreSame(byInterface[0], byBaseClass[0]);
}
[测试]
公共void TestMethod1()
{
IKernel kernel=新的标准内核();
//两全其美
Bind(x=>x
.FromThisAssembly()中的
.SelectAllClasses().InheritedFrom()
.BindSelection((type,baseTypes)=>新列表{typeof(IInterface),typeof(BaseClass)})
.Configure(b=>b.InSingletonScope())
);
List byInterface=新列表(kernel.GetAll());
List byBaseClass=新列表(kernel.GetAll());
AreName(byInterface[0],byBaseClass[0]);
}

但是当我尝试将两个绑定放在不同的模块中时,这将不会有帮助。还是这是个坏主意?

范围是为绑定定义的。两个绑定无法共享作用域

你应该做什么:

  • 使用接口而不是
    BaseClass
  • Fins是一种编码约定,用于定义什么类型的Cals是Singleton。e、 g.特殊命名,如以服务结尾
  • 使用BindAllInterfaces绑定它们

  • 当使用约定时,这不应该从消费者的角度进行,而应该从服务提供者的角度进行。因此,不同模块中的不同接口类型不需要绑定。

    范围是为绑定定义的。两个绑定无法共享作用域

    你应该做什么:

  • 使用接口而不是
    BaseClass
  • Fins是一种编码约定,用于定义什么类型的Cals是Singleton。e、 g.特殊命名,如以服务结尾
  • 使用BindAllInterfaces绑定它们

  • 当使用约定时,这不应该从消费者的角度进行,而应该从服务提供者的角度进行。因此,不需要为不同模块中的不同接口类型进行绑定。

    我不喜欢提取基类接口来让DI工作。因此,我发布的解决方案甚至可以与接口和基类一起工作。我只需要重新思考我的模块。事实上,我的基类是“BaseSpellInfo”,接口是“ILearnable”。所以有一个学习系统(模块)处理所有可以学习的东西(不仅仅是咒语),还有描述咒语的咒语信息,应该是单例。如果我在两个模块中定义它们,我总是会得到每个拼写信息的两个实例,一个在学习的上下文中,一个在施法的上下文中。我不喜欢提取基类接口来让DI工作。因此,我发布的解决方案甚至可以与接口和基类一起工作。我只需要重新思考我的模块。事实上,我的基类是“BaseSpellInfo”,接口是“ILearnable”。所以有一个学习系统(模块)处理所有可以学习的东西(不仅仅是咒语),还有描述咒语的咒语信息,应该是单例。如果我在两个模块中定义它们,我总是会得到每个咒语信息的两个实例,一个在学习环境中,一个在施法环境中。