【问题标题】:Where is a singleton instance stored in ninject?ninject 中存储的单例实例在哪里?
【发布时间】:2017-11-15 16:46:03
【问题描述】:

标题说明了一切。当我这样做时:

var kernel = new StandardKernel();
kernel.Bind<IMyClass>().To<MyClass>().InSingletonScope();
var myClass = kernel.Get<IMyClass>();

MyClass 的实例存储在哪里?它是否存储在全球某处的静态字典中?还是存储在内核实例中?

例如,如果我这样做:

var kernel1 = new StandardKernel();
var kernel2 = new StandardKernel();
kernel1.Bind<IMyClass>().To<MyClass>().InSingletonScope();
kernel2.Bind<IMyClass>().To<MyClass>().InSingletonScope();
var myClass1 = kernel1.Get<IMyClass>();
var myClass2 = kernel2.Get<IMyClass>();

myClass1 是与 myClass2 相同的实例还是不同的实例。

跳到一个不可避免的问题“你为什么需要这样做?”:没关系。这不是问题的重点。我有我的理由,只是想知道这件作品是如何运作的。

【问题讨论】:

    标签: c# .net dependency-injection ninject ninject-extensions


    【解决方案1】:

    所以 Ninject 将它们存储在这里:

      /// <summary>Tracks instances for re-use in certain scopes.</summary>
      public class Cache : NinjectComponent, ICache, INinjectComponent, IDisposable, IPruneable
      {
        /// <summary>
        /// Contains all cached instances.
        /// This is a dictionary of scopes to a multimap for bindings to cache entries.
        /// </summary>
        private readonly IDictionary<object, Multimap<IBindingConfiguration, Cache.CacheEntry>> entries = (IDictionary<object, Multimap<IBindingConfiguration, Cache.CacheEntry>>) new Dictionary<object, Multimap<IBindingConfiguration, Cache.CacheEntry>>((IEqualityComparer<object>) new WeakReferenceEqualityComparer());
    ...
    

    并且缓存的范围是内核的实例。

    myClass1 是与 myClass2 相同的实例还是它们是 不同的实例。

    不同。缓存不是静态的。

    【讨论】:

    • 我在 juharr 的建议下进行了一些测试(请参阅原始问题中的评论),这些测试表明不同。我在我的问题中使用了与上面相同的代码,然后进行了测试以查看是否“myClass1 == myClass2”。它们实际上是同一个实例。
    • @computrius 我运行了相同的测试并获得了两个不同的实例,这是预期的行为。请注意,上面发布的代码来自 Ninject 来源github.com/ninject/Ninject/blob/…
    • @computrius 你的测试代码可能有缺陷。可能的问题:类型是否覆盖 Equals 方法?不同的内核实例会创建不同的单例实例。
    • 再次运行它,似乎我错了。将此标记为答案。
    【解决方案2】:

    对于其他想知道的人:它将它存储在内核之外。您将获得具有两个内核的相同实例。

    编辑 - 我运行测试得出这个结论:

    var kernel1 = new StandardKernel();
    var kernel2 = new StandardKernel();
    kernel1.Bind<IMyClass>().To<MyClass>().InSingletonScope();
    kernel2.Bind<IMyClass>().To<MyClass>().InSingletonScope();
    var myClass1 = kernel1.Get<IMyClass>();
    var myClass2 = kernel2.Get<IMyClass>();
    var same = myClass1 == myClass2;
    Console.WriteLine(same ? "Same" : "Different");
    

    输出:相同

    再次编辑: 我一定是打错了,因为我再次测试并得到“不同”。

    【讨论】:

    • 不知道为什么这被否决了,因为我的测试表明它实际上是正确的。我用我运行的测试编辑了答案。除非可以向我解释差异,否则这将是两天后接受的答案..
    • 我不认为它会是一样的。尝试object.ReferenceEquals 方法来测试引用是否相等。也许您的 MyClass 类覆盖了 == 运算符?
    • 它被否决了,因为它不是真的。除了 Yacoub 已经提到的内容之外,没有其他理由应该返回“Same”。
    • 另外,您应该发布测试所需的完整代码。缺少接口/类的定义和实现。
    • 有趣,它与引用相等不同。那么,有什么区别呢?我刚刚测试了一个没有为“==”配置重载的基类。我的理解是 myClass.Equals(...) 的唯一原因是 == 将比较参考而不是内容。不是这样吗?也许我只是有一个错字并忽略了它。
    猜你喜欢
    • 2021-09-07
    • 2011-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多