Binding 我可以在Ninject中为我的对象进行分段范围配置吗?

Binding 我可以在Ninject中为我的对象进行分段范围配置吗?,binding,configuration,scope,ninject,conventions,Binding,Configuration,Scope,Ninject,Conventions,我们在代码库中提供服务的几个案例中都知道代码库中服务提供者的作用域和生存期规则。我们希望在库本身中配置该信息,而不必将该知识冒泡到合成根 我一直无法确定是否可以在当前版本的Ninject中实现这一点 using System; using System.Diagnostics.CodeAnalysis; using Ninject; using Ninject.Extensions.Conventions; using NUnit.Framework; using Ninject.Modules

我们在代码库中提供服务的几个案例中都知道代码库中服务提供者的作用域和生存期规则。我们希望在库本身中配置该信息,而不必将该知识冒泡到合成根

我一直无法确定是否可以在当前版本的Ninject中实现这一点

using System;
using System.Diagnostics.CodeAnalysis;
using Ninject;
using Ninject.Extensions.Conventions;
using NUnit.Framework;
using Ninject.Modules;

[TestFixture]
public class Spike
{
    private IKernel kernel;

    [SetUp]
    public void SetUp()
    {
        this.kernel = new StandardKernel();

        this.kernel.Load(new Registry());

        this.kernel.Bind(x => x
            .FromThisAssembly()
            .SelectAllClasses()
            .BindAllInterfaces()
            );
    }

    [TearDown]
    public void TearDown()
    {
        Thing1.ResetCounts();
    }

    [Test]
    public void GetThing1AndThing2()
    {
        // arrange
        var thing1 = this.kernel.Get<Thing1>();
        var thing2 = this.kernel.Get<Thing1>();

        // act
        thing1.DoTheWork();
        thing2.DoTheWork();

        // assert
        Assert.AreEqual(1, Thing1.ConstructorCount, "wrong number of constructor invocations");
        Assert.AreEqual(2, Thing1.DoTheWorkCount, "wrong number of method invocations");
    }

    [Test]
    public void GetIThing1AndIThing2()
    {
        // arrange
        var thing1 = this.kernel.Get<IThing1>();
        var thing2 = this.kernel.Get<IThing1>();

        // act
        thing1.DoTheWork();
        thing2.DoTheWork();

        // assert
        Assert.AreEqual(1, Thing1.ConstructorCount, "wrong number of constructor invocations");
        Assert.AreEqual(2, Thing1.DoTheWorkCount, "wrong number of method invocations");
    }

    public class Registry : NinjectModule
    {
        public override void Load()
        {
            Bind<Thing1>().ToSelf().InSingletonScope();
        }
    }

    public interface IThing1
    {
        void DoTheWork();
    }

    public class Thing1 : IThing1
    {
        public static int ConstructorCount { get; set; }
        public static int DoTheWorkCount { get; set; }

        public Thing1()
        {
            Console.WriteLine("Thing1.ctor underway");
            ++Thing1.ConstructorCount;
        }

        public void DoTheWork()
        {
            Console.WriteLine("Thing1.DoTheWork underway");
            ++Thing1.DoTheWorkCount;
        }

        public static void ResetCounts()
        {
            Thing1.ConstructorCount = 0;
            Thing1.DoTheWorkCount = 0;
        }
    }
}
使用系统;
使用System.Diagnostics.CodeAnalysis;
使用Ninject;
使用Ninject.Extensions.Conventions;
使用NUnit.Framework;
使用Ninject.Modules;
[测试夹具]
公开课扣球
{
私有IKernel内核;
[设置]
公共作废设置()
{
this.kernel=新的标准内核();
this.kernel.Load(new Registry());
this.kernel.Bind(x=>x
.FromThisAssembly()中的
.SelectAllClasses()
.BindAllInterfaces()
);
}
[撕裂]
公共无效拆卸()
{
内容1.重置计数();
}
[测试]
public void getthing1和thing2()
{
//安排
var thing1=this.kernel.Get();
var thing2=this.kernel.Get();
//表演
事情1.DoTheWork();
事情2.做工;
//断言
AreEqual(1,Thing1.ConstructorCount,“构造函数调用次数错误”);
AreEqual(2,Thing1.DoTheWorkCount,“错误的方法调用次数”);
}
[测试]
公共无效GetThing1和2()
{
//安排
var thing1=this.kernel.Get();
var thing2=this.kernel.Get();
//表演
事情1.DoTheWork();
事情2.做工;
//断言
AreEqual(1,Thing1.ConstructorCount,“构造函数调用次数错误”);
AreEqual(2,Thing1.DoTheWorkCount,“错误的方法调用次数”);
}
公共类注册表:NinjectModule
{
公共覆盖无效负载()
{
Bind().ToSelf().InSingletonScope();
}
}
公共接口iTing1
{
虚空做工作();
}
公共类内容1:I类内容1
{
公共静态int构造函数计数{get;set;}
公共静态int DoTheWorkCount{get;set;}
公共事务1()
{
Console.WriteLine(“Thing1.1”);
++1.构造计数;
}
公共无效DoTheWork()
{
Console.WriteLine(“Thing1.DoTheWork在进行中”);
++工作计数;
}
公共静态无效重置计数()
{
Thing1.ConstructorCount=0;
Thing1.DoTheWorkCount=0;
}
}
}
在这个测试用例中,iLibrary由
注册表
Thing1
IThing1
类表示。库的用户是测试夹具,其中
Spike.SetUp()
方法显示了理想情况下我们希望库用户编写的代码(在该方法中,他们将传入包含dll的路径,而不是新建
注册表
对象)

编写好代码后,在
Spike.getthing1和thing2()
中多次获取
Thing1
服务将显示所需的单例行为。通过其发布的接口多次获取
Thing1
服务,如
Spike.getThing1andThing2()
中所示,不会显示单例行为,而是构建两个独立的
Thing1
对象


那么,有没有可能做到我所要求的:在组成根目录时执行扫描时,在DLL本身中指定单例行为?

您需要引入约定。例如,添加指定范围的属性或使用命名约定,以便您可以从名称中识别范围

然后正确设置绑定约定。例如

this.kernel.Bind(x => x
    .FromThisAssembly()
    .SelectAllClasses()
    .WithAttribute<SingletonAttribute>()
    .BindAllInterfaces()
    .Configure(binding => binding.InSingletonScope());

this.kernel.Bind(x => x
    .FromThisAssembly()
    .SelectAllClasses()
    .WithAttribute<TransientAttribute>()
    .BindAllInterfaces());
this.kernel.Bind(x=>x
.FromThisAssembly()中的
.SelectAllClasses()
.WithAttribute()
.BindAllInterfaces()
.Configure(binding=>binding.InSingletonScope());
this.kernel.Bind(x=>x
.FromThisAssembly()中的
.SelectAllClasses()
.WithAttribute()
.BindAllInterfaces());