简体   繁体   English

在Ninject中将单例绑定到多个服务

[英]Binding singleton to multiple services in Ninject

I have a problem which seems very similar to the one described in http://markmail.org/message/6rlrzkgyx3pspmnf which is about the singleton actually creating more than a single instance if you're accessing it using different service types. 我有一个问题,似乎与http://markmail.org/message/6rlrzkgyx3pspmnf中描述的问题非常相似,如果您使用不同的服务类型访问它,实际上创建的单个实例不仅仅是单个实例。

I'm using the latest release of Ninject 2 for Compact Framework and the exact issue I'm having is that if I bind the same provider method to: 我正在使用最新版本的Ninject 2 for Compact Framework,我遇到的确切问题是,如果我将相同的提供程序方法绑定到:

Func<Service> serviceCreator = () => new Service(false);
kernel.Bind<IService>().ToMethod(serviceCreator).InSingletonScope();
kernel.Bind<Service>().ToMethod(serviceCreator).InSingletonScope();

It seems to be creating 2 instances of Service if I resolve both as IService and Service. 如果我将它们解析为IService和Service,它似乎创建了2个Service实例。

This causes a circular dependency exception when resolving Service. 这在解析Service时会导致循环依赖性异常。

Is this by design, or is it a bug? 这是设计,还是一个bug?

In V3, there is finally a solution for this in the shape of new overloads on Bind , see this related: question . 在V3中,最终Bind新的重载形式解决了这个问题 ,请参阅以下相关:问题


If you want the singleton to be shared, you need to change your second Bind to: 如果您希望共享单例,则需要将第二个Bind更改为:

kernel.Bind<Service>().ToMethod(()=>kernel.Get<IService>()).InSingletonScope();

Re circular references and confusion etc. Internally the implicit self-binding will add an implicit binding registration for Service. 重复循环引用和混淆等。在内部,隐式自绑定将为Service添加隐式绑定注册。 You should post the exception. 你应该发布例外。

EDIT: Re your comment. 编辑:重新评论。 If you do it like this: 如果你这样做:

Func<Service> serviceCreator = () => new Service(false);
kernel.Bind<Service>().ToMethod(serviceCreator).InSingletonScope();
kernel.Bind<IService>().ToMethod(()=>kernel.Get<Service>()).InSingletonScope();

Then no implicit Class Self Binding gets generated when IService gets Resolved - it uses the existing one. 然后,当IService被解析时,不会生成隐式类自绑定 - 它使用现有的。

There was another Q here on SO in recent weeks someone was doing this type of thing but was running into an issue with IInitializable - that example would have the correct ordering but the one above makes sense based on my reading of the source and the way in which it generates the implicit class self-bindings. 最近几周,SO上有另一个问题,有人正在做这类事情,但是遇到了IInitializable的问题 - 这个例子会有正确的顺序,但上面的那个基于我对源代码和方法的解读是有意义的。它生成隐式类自绑定。

By the way, Ninject 3 allows this syntax : 顺便说一句,Ninject 3 允许这种语法

kernel.Bind<IService, Service>().ToMethod(serviceCreator).InSingletonScope();

Or, similarly: 或者,类似地:

kernel.Bind(typeof(IService), typeof(Service)).ToMethod(serviceCreator).InSingletonScope();

This latter approach works better if you have many services, or if you discovered the services dynamically at runtime (you can pass the params -style arguments as an array directly). 如果您有许多服务,或者如果您在运行时动态发现服务(后者可以直接将params style参数作为数组传递),则后一种方法可以更好地工作。

We used Ruben's method in our project, but found that it wasn't intuitive why you were going back to the Kernel in your binding. 我们在项目中使用了Ruben的方法,但发现为什么要在绑定中返回内核并不直观。 I created an extension method and helper class (below) so you can do this: 我创建了一个扩展方法和辅助类(如下所示),所以你可以这样做:

kernel.Bind<IService>().ToExisting().Singleton<Service>();

That seemed to express the intent more clearly to me. 这似乎更清楚地表达了我的意图。

public static class DIExtensions
{
    public static ToExistingSingletonSyntax<T> ToExisting<T>(this IBindingToSyntax<T> binding)
    {
        return new ToExistingSingletonSyntax<T>(binding);
    }
}

// Had to create this intermediate class because we have two type parameters -- the interface and the implementation,
// but we want the compiler to infer the interface type and we supply the implementation type.  C# can't do that.
public class ToExistingSingletonSyntax<T>
{
    internal ToExistingSingletonSyntax(IBindingToSyntax<T> binding)
    {
        _binding = binding;
    }

    public IBindingNamedWithOrOnSyntax<T> Singleton<TImplementation>() where TImplementation : T
    {
        return _binding.ToMethod(ctx => ctx.Kernel.Get<TImplementation>()).InSingletonScope();
    }


    private IBindingToSyntax<T> _binding;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM