Ninject 单例未作为单例注入依赖 Class

Ninject Singleton not being injected as Singleton into Dependent Class

我正在创建一个 PersonalityConfiguration class,我希望它成为一个单例,并且在大多数情况下,单例绑定工作正常。除非此 "Singleton" 通过 Class 的构造函数中的 IPersonalityProvider 接口绑定。注入绑定时,它不是单例,不是 PersonalityConfiguration 的同一个实例,而是每次都是一个新实例。我如何通过 IPersonalityProvider 接口将同一个单例绑定到依赖的 classes?

我有以下界面和 Class 定义

接口 IPersonalityProvider

interface IPersonalityProvider
{
    void BeHappy();
}

Class个性配置

class PersonalityConfiguration : IPersonalityProvider
{
    private int m_personalityScale = 0;
    public PersonalityConfiguration()
    {
        m_personalityScale = 0;
    }

    public void BeHappy()
    {
        throw new NotImplementedException();
    }
}

Class 人

class Person
{
    public Person(IPersonalityProvider personality)
    {
        Personality = personality;
    }

    public IPersonalityProvider Personality { get; set; }
}

我的Ninject模块如下

class ProgramNinjectModule : NinjectModule
{
    public override void Load()
    {
        Bind<PersonalityConfiguration>().ToSelf().InSingletonScope();
        Bind<IPersonalityProvider>().To<PersonalityConfiguration>();
    }
}

这是我的主要内容

   static void Main(string[] args)
    {
        using (var nKernel = new StandardKernel(new ProgramNinjectModule()))
        {

            //Singleton works here
            PersonalityConfiguration crazy1 = nKernel.Get<PersonalityConfiguration>();  
            PersonalityConfiguration crazy2 = nKernel.Get<PersonalityConfiguration>();  
            Assert.AreEqual(crazy1, crazy2); //True as Expected

            //Expecting PersonalityConfig Singleton to bind to Person1 and 2, does not
            Person person1 = nKernel.Get<Person>();  
            Person person2 = nKernel.Get<Person>();
            Assert.AreEqual(person1.Personality, person2.Personality);  //False, Bombs

            //Obviously this works
            Person person3 = new Person(crazy1);
            Person person4 = new Person(crazy1);
            Assert.AreEqual(person3.Personality, person4.Personality);  //True as Expected
        }

    }

看来我使用了以下绑定并且有效

class ProgramNinjectModule : NinjectModule
{
    public override void Load()
    {
        Bind<PersonalityConfiguration>().ToSelf().InSingletonScope();
        Bind<IPersonalityProvider>().ToMethod(n => n.Kernel.Get<PersonalityConfiguration>()).WhenInjectedInto<Person>();
    }
}

实现您想要的目标的简洁方法是通过一个绑定:

Bind<IPersonalityProvider, PersonalityConfiguration>()
    .To<PersonalityConfiguration>()
    .InSingletonScope();

这意味着每当 ninject 被请求 return 一个 IPersonalityProvider 一个 PersonalityConfiguration 它会 return PersonalityConfiguration.

的相同(单例)实例

我已经使用以下代码验证它可以正常工作:

using System;
using FluentAssertions;
using Ninject;
using Ninject.Modules;
using Xunit;

namespace NinjectTest.SingletonBoundToMultipleTypes
{
    interface IPersonalityProvider
    {
        void BeHappy();
    }

    class PersonalityConfiguration : IPersonalityProvider
    {
        private int m_personalityScale = 0;
        public PersonalityConfiguration()
        {
            m_personalityScale = 0;
        }

        public void BeHappy()
        {
            throw new NotImplementedException();
        }
    }

    class Person
    {
        public Person(IPersonalityProvider personality)
        {
            Personality = personality;
        }

        public IPersonalityProvider Personality { get; set; }
    }

    class ProgramNinjectModule : NinjectModule
    {
        public override void Load()
        {
            Bind<IPersonalityProvider, PersonalityConfiguration>()
                .To<PersonalityConfiguration>()
                .InSingletonScope();
        }
    }

    public class Test
    {
        [Fact]
        public void PerformTest()
        {
            using (var nKernel = new StandardKernel(new ProgramNinjectModule()))
            {
                //Singleton works here
                PersonalityConfiguration crazy1 = nKernel.Get<PersonalityConfiguration>();
                PersonalityConfiguration crazy2 = nKernel.Get<PersonalityConfiguration>();
                ReferenceEquals(crazy1, crazy2).Should().BeTrue();

                //Expecting PersonalityConfig Singleton to bind to Person1 and 2, does not
                Person person1 = nKernel.Get<Person>();
                Person person2 = nKernel.Get<Person>();
                ReferenceEquals(person1.Personality, person2.Personality)
                    .Should().BeTrue();

                //Obviously this works
                Person person3 = new Person(crazy1);
                Person person4 = new Person(crazy1);
                ReferenceEquals(person3.Personality, person4.Personality)
                    .Should().BeTrue();
            }
        }
    }
}