Ninject: Как получить доступ к корневому объекту NamedScope с завода
В моем приложении я использую 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
на завод.
1 ответ
Да, вы правы, из коробки Ninject не может сделать .DefinesNamedScope().InNamedScope()
, За исключением, может быть, позднего "создания" (фабричного, ленивого), это все равно не сработает, потому что это создаст циклическую зависимость.
Самый простой способ добиться того, чего вы хотите, - создать "корень корня"... ну, всего один класс ActualRoot
который связан с DefinesNamedScope()
и получает IRootScope
вводится, что снова будет связано с .InNamedScope()
, Плохая вещь в том, что вам нужно будет ввести /Get<>
ActualRoot
вместо IRootScope
,
Насколько я помню, вы также можете сделать следующее:
Bind<IRootScope>().To<RootScope>()
.InNamedScope(scopeName);
а затем получить его следующим образом:
IResolutionRoot.Get<IRootScope>(new NamedScopeParameter(scopeName));
Таким образом, вам не нужно DefinesNamedScope()
,