【问题标题】:Ninject: How to access root object of NamedScope from factoryNinject:如何从工厂访问 NamedScope 的根对象
【发布时间】:2014-10-28 16:50:56
【问题描述】:

在我的应用程序中,我使用了 Ninject 和 NamedScopeExtension。对象图中较深的对象之一需要访问定义命名范围的根对象。在我看来,DefinesNamedScope() 并不意味着InNamedScope(),而是在我请求根时创建了一个新的根对象。

例子:

using System;
using Ninject;
using Ninject.Extensions.NamedScope;
using Ninject.Syntax;

namespace NInjectNamedScope
{
    public interface IScopeRoot
    {
        Guid Guid { get; }
        void DoSomething();
    }

    public interface IFactory
    {
        Guid Guid { get; }
        IOther CreateOther();
    }

    public interface IOther
    {
        void SayHello();
    }

    internal class ScopeRoot : IScopeRoot
    {
        private readonly IFactory m_factory;
        private readonly IResolutionRoot m_kernel;
        public Guid Guid { get; private set; }

        public ScopeRoot(IFactory factory, IResolutionRoot kernel)
        {
            m_factory = factory;
            m_kernel = kernel;
            Guid = Guid.NewGuid();
        }

        public void DoSomething()
        {
            Console.WriteLine("ScopeRoot.DoSomething(): Entering");
            Console.WriteLine("ScopeRoot GUID: {0}", Guid);
            Console.WriteLine("IFactory  GUID: {0}", m_factory.Guid);
            var other = m_factory.CreateOther();
            Console.WriteLine("ScopeRoot.DoSomething(): Other created");
            other.SayHello();
            Console.WriteLine("ScopeRoot.DoSomething(): Exiting");
        }
    }

    internal class Factory : IFactory
    {
        private IResolutionRoot m_kernel;

        public Guid Guid { get; private set; }

        public Factory(IResolutionRoot kernel)
        {
            m_kernel = kernel;
            Guid = Guid.NewGuid();
        }
        public IOther CreateOther()
        {
            return m_kernel.Get<IOther>();
        }
    }

    internal class Other : IOther
    {
        private readonly IScopeRoot m_root;
        private readonly IFactory m_factory;

        public Other(IScopeRoot root, IFactory factory)
        {
            m_root = root;
            m_factory = factory;
        }

        public void SayHello()
        {
            Console.WriteLine("Other.SayHello(): Hello");
            Console.WriteLine("Our IScopeRoot has GUID: {0}", m_root.Guid);
            Console.WriteLine("Our IFactory has GUID:   {0}", m_factory.Guid);
        }
    }

    public class MainClass
    {
        public static void Main(string[] args)
        {
            var kernel = new StandardKernel();

            kernel.Bind<IScopeRoot>().To<ScopeRoot>().DefinesNamedScope("RootScope");
            kernel.Bind<IFactory>().To<Factory>().InNamedScope("RootScope");
            kernel.Bind<IOther>().To<Other>().InNamedScope("RootScope");

            var root = kernel.Get<IScopeRoot>();
            root.DoSomething();

            Console.ReadKey();
        }
    }
}

在此示例中,Other 与根接收相同的 Factory 实例,但创建了一个新的 ScopeRoot 实例,而不是注入定义命名范围的现有实例。

如何访问工厂中命名作用域的根目录?请注意,此示例已简化。实际上,作用域根和工厂方法之间有好几层对象,所以我不能简单地将this 传递给工厂。

【问题讨论】:

    标签: dependency-injection ninject ninject-extensions


    【解决方案1】:

    是的,你是对的,开箱即用的 Ninject 无法做到.DefinesNamedScope().InNamedScope()。除了后期的“创建”(工厂,懒惰)之外,这无论如何都无法工作,因为它会创建一个循环依赖。

    实现你想要的最简单的方法是创建一个“根的根”......好吧只有一个类ActualRootDefinesNamedScope()绑定并注入IRootScope,这又将是与.InNamedScope() 绑定。这样做的坏处是,您需要注入/Get&lt;&gt;ActualRoot 而不是 IRootScope

    据我记得,你也可以做的是:

    Bind<IRootScope>().To<RootScope>()
        .InNamedScope(scopeName);
    

    然后按如下方式检索:

    IResolutionRoot.Get<IRootScope>(new NamedScopeParameter(scopeName));
    

    这样你就不需要DefinesNamedScope()

    【讨论】:

    • 您的解决方案非常有效,非常感谢!第二个建议(IBindingRoot.Bind&lt;IRootScope&gt;().To&lt;RootScope&gt;().WithParameter(new NamedScopeParameter(scopeName));)不起作用,所以我冒昧地将它从答案中删除。
    猜你喜欢
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-23
    相关资源
    最近更新 更多