C# 尼尼特。将所有接口绑定到singleton作用域中的同一类
我希望一个类既是一个对象,它提供关于后端的信息,也是一个类,当服务器停机时后端会通知它(例如ZooKeeper或WCF)。 问题是,当我将同一个类绑定到singleton范围中的两个不同接口时,Ninject会创建两个实例或抛出一个错误,具体取决于我的操作方式 以下示例必须打印相同的Guid,并且必须绑定所有接口 例如: Program.csC# 尼尼特。将所有接口绑定到singleton作用域中的同一类,c#,dependency-injection,singleton,ninject,C#,Dependency Injection,Singleton,Ninject,我希望一个类既是一个对象,它提供关于后端的信息,也是一个类,当服务器停机时后端会通知它(例如ZooKeeper或WCF)。 问题是,当我将同一个类绑定到singleton范围中的两个不同接口时,Ninject会创建两个实例或抛出一个错误,具体取决于我的操作方式 以下示例必须打印相同的Guid,并且必须绑定所有接口 例如: Program.cs using System; using Ninject; using Ninject.Modules; namespace ConsoleApplica
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();
}
}
}
namespace ConsoleApplication1
{
public interface IListener
{
void Send();
}
}
namespace ConsoleApplication1
{
public interface IState
{
void Inform();
}
}
IState.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();
}
}
}
namespace ConsoleApplication1
{
public interface IListener
{
void Send();
}
}
namespace ConsoleApplication1
{
public interface IState
{
void Inform();
}
}
StateClass.cs
使用制度
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-Version 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()));
}
}
}
使用Ninject.Modules;
使用Ninject.Extensions.Conventions;
命名空间控制台应用程序1
{
类绑定:NinjectModule
{
公共覆盖无效负载()
{
Bind(x=>x
.FromAssemblyContaining()
.SelectAllClasses()
.继承自()
.BindAllInterfaces()
.Configure(y=>y.InSingletonScope());
//取消注释以下绑定以查看异常
//问题是我们事先不知道这一点
//Bind(x=>x
//.FromAssemblyContaining()
//.SelectAllClasses()
//.继承自()
//.BindAllInterfaces()
//.Configure(y=>y.InSingletonScope());
}
}
}
Bindings.cs-版本2-无例外,但应用程序打印不同的GUI:
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();
}
}
}
使用Ninject.Modules;
使用Ninject.Extensions.Conventions;
命名空间控制台应用程序1
{
类绑定:NinjectModule
{
公共覆盖无效负载()
{
Kernel.Bind().To().InSingletonScope();
Kernel.Bind().To().InSingletonScope();
}
}
}
因此,我认为在您的模块中,您必须告诉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>());
}
}
类绑定:Ninject模块
{
公共覆盖无效负载()
{
Kernel.Bind().ToSelf().InSingletonScope();
Kernel.Bind().ToMethod(ctx=>ctx.Kernel.Get());
Kernel.Bind().ToMethod(ctx=>ctx.Kernel.Get());
}
}
Ninject.Conventions部分如何,当一个人的目标是插件基础设施时?我认为这些约定将始终单独处理每个接口;换句话说,为每个接口创建一个单例,不管它是由什么实现的。如果您真的希望它是可插拔的,我认为您需要另一层抽象——创建一个单独的代理类(作为单例),它将保存IListener实现和IState实现都需要访问的任何数据(本例中的Guid)。这样,框架对接口的实现是不可知的。