Ninject Singleton没有作为Singleton注入依赖类

时间:2015-06-26 03:49:26

标签: c# binding dependency-injection singleton ninject

我正在创建一个PersonalityConfiguration类,我想成为一个Singleton,而且大多数情况下Singleton绑定工作正常。除了这个" Singleton"通过类的构造函数中的IPersonalityProvider接口绑定。当Binding被注入时,它不是Singleton,不是PersonalityConfiguration的相同实例,而是每次都是一个新实例。如何通过IPersonalityProvider接口将相同的Singleton绑定到依赖类?

我有以下的Inteface和Class Definitions

接口IPersonalityProvider

interface IPersonalityProvider
{
    void BeHappy();
}

Class PersonalityConfiguration

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

我的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
        }

    }

2 个答案:

答案 0 :(得分:4)

通过单一绑定实现您想要的干净方式:

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

这意味着只要请求ninject返回IPersonalityProvider PersonalityConfiguration,它就会返回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();
            }
        }
    }
}

答案 1 :(得分:1)

看起来我使用了以下绑定并且工作正常

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