Ninject。将所有接口绑定到单一范围内的同一个类

时间:2015-02-26 09:49:21

标签: c# dependency-injection singleton ninject

我希望一个类既是一个提供有关后端信息的对象,另一个是后端在服务器关闭时通知的类(例如ZooKeeper或WCF)。 问题是当我将同一个类绑定到单例范围内的两个不同接口时,Ninject会创建两个实例或引发错误,具体取决于我的操作方式。

以下示例必须打印相同的Guid,并且必须绑定所有接口。

示例:

Program.cs的

using System;
using Ninject;
using Ninject.Modules;

namespace ConsoleApplication1
{
    static class Program
    {
        static void Main(string[] args)
        {
            IKernel kernel = new StandardKernel();
            kernel.Load(new INinjectModule[] { new Bindings() });
            Console.WriteLine("First interface");
            var i1 = kernel.Get<IState>();
            i1.Inform();
            Console.WriteLine("Second interface");
            var i2 = kernel.Get<IListener>();
            i2.Send();
            Console.ReadKey();
        }
    }
}

IListener.cs

namespace ConsoleApplication1
{
    public interface IListener
    {
        void Send();
    }
}

IState.cs

namespace ConsoleApplication1
{
    public interface IState
    {
        void Inform();
    }
}

StateClass.cs 使用System;

namespace ConsoleApplication1
{
    public class StateClass : IState, IListener
    {
        private readonly String _seed;
        public StateClass()
        {
            _seed = Guid.NewGuid().ToString();
        }
        public void Send()
        {
            Console.WriteLine(_seed);
        }

        public void Inform()
        {
            Console.WriteLine(_seed);
        }
    }
}

Bindings.cs - 版本1 在此示例中,如果代码已注释,则一切正常。问题是我事先不知道如果一个类强迫 IState 接口它还会 IListener 接口:

using Ninject.Modules;
using Ninject.Extensions.Conventions;

namespace ConsoleApplication1
{
    class Bindings : NinjectModule
    {
        public override void Load()
        {
            Kernel.Bind(x => x
                .FromAssemblyContaining<IState>()
                .SelectAllClasses()
                .InheritedFrom<IState>()
                .BindAllInterfaces()
                .Configure(y => y.InSingletonScope()));
            //uncomment the following binding to see an exception
            //problem is we dont know this in advance
            //Kernel.Bind(x => x
            //    .FromAssemblyContaining<IListener>()
            //    .SelectAllClasses()
            //    .InheritedFrom<IListener>()
            //    .BindAllInterfaces()
            //    .Configure(y => y.InSingletonScope()));
        }
    }
}

Bindings.cs - 版本2 - 没有例外,但是应用程序会打印不同的Guid:

using Ninject.Modules;
using Ninject.Extensions.Conventions;

    namespace ConsoleApplication1
    {
        class Bindings : NinjectModule
        {
            public override void Load()
            {
                Kernel.Bind<IListener>().To<StateClass>().InSingletonScope();
                Kernel.Bind<IState>().To<StateClass>().InSingletonScope();
            }
        }
    }

1 个答案:

答案 0 :(得分:2)

所以我认为在你的模块中你必须告诉Ninject两个接口都使用相同的对象。如果你不这样做,Ninject将始终假设每个接口都有自己的单例。

class Bindings : NinjectModule
{
    public override void Load()
    {
        Kernel.Bind<StateClass>().ToSelf().InSingletonScope();
        Kernel.Bind<IListener>().ToMethod(ctx => ctx.Kernel.Get<StateClass>());
        Kernel.Bind<IState>().ToMethod(ctx => ctx.Kernel.Get<StateClass>());
    }
}