9

我有一个问题,看起来与http://markmail.org/message/6rlrzkgyx3pspmnf中描述的问题非常相似,如果您使用不同的服务类型访问它,单例实际上会创建多个实例。

我正在使用最新版本的 Ninject 2 for Compact Framework,我遇到的确切问题是,如果我将相同的提供程序方法绑定到:

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

如果我同时解析为 IService 和 Service,它似乎正在创建 2 个服务实例。

这在解析 Service 时会导致循环依赖异常。

这是设计使然,还是错误?

4

3 回答 3

11

在 V3 中,终于有了新的重载Bind形式的解决方案,请参阅相关:问题


如果要共享单例,则需要将第二个更改Bind为:

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

再循环引用和混淆等。内部隐式自绑定将为服务添加隐式绑定注册。您应该发布异常。

编辑:重新发表您的评论。如果你这样做:

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

然后在 Resolved 时不会生成隐式 Class Self Binding IService- 它使用现有的。

最近几周这里有另一个关于 SO 的问题,有人正在做这类事情,但遇到了 IInitializable 的问题- 该示例的顺序正确,但根据我对源代码的阅读和输入方式,上述示例是有道理的它生成隐式类自绑定。

于 2010-06-30T10:02:28.370 回答
6

顺便说一句,Ninject 3允许这种语法

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

或者,类似地:

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

如果您有许多服务,或者如果您在运行时动态发现服务(您可以params直接将 -style 参数作为数组传递),则后一种方法效果更好。

于 2012-08-07T22:08:07.267 回答
4

我们在项目中使用了 Ruben 的方法,但发现为什么要在绑定中返回内核并不直观。我创建了一个扩展方法和帮助类(如下),所以你可以这样做:

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

这似乎更清楚地向我表达了意图。

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;
}
于 2011-03-04T15:34:36.787 回答