2014-10-28 3 views
2

내 응용 프로그램에서 Ninject와 NamedScopeExtension을 사용하고 있습니다. 개체 그래프에서 더 깊은 개체 중 하나는 명명 된 범위를 정의한 루트 개체에 대한 액세스가 필요합니다. DefinesNamedScope()InNamedScope()을 암시하지 않으며 대신 루트를 요청할 때 새로운 루트 개체가 만들어집니다.Ninject : 공장에서 NamedScope의 루트 객체에 접근하는 방법

예이 예에서

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(); 
     } 
    } 
} 

, 루트 마찬가지로 OtherFactory의 동일한 인스턴스를 수신하지만, ScopeRoot의 새로운 인스턴스 대신 지정된 범위를 정의 기존 인스턴스를 주입 생성된다.

어떻게하면 공장에서 명명 된 범위의 루트에 액세스 할 수 있습니까? 이 예제는 단순화되어 있습니다. 실제로 범위 루트와 팩토리 메서드 사이에는 여러 레이어의 개체가 있으므로 단순히 this을 전달할 수는 없습니다.

답변

2

네가 맞다. Ninject가 할 수없는 것 .DefinesNamedScope().InNamedScope(). 늦은 "창조"(공장, 게으른)를 제외하고 어쨌든 이것은 작동하지 않을 수 있습니다.주기적인 의존성이 생기기 때문입니다.

당신이 원하는 것을 달성하는 가장 간단한 방법은 ...는 "루트의 루트"를 만드는 것입니다 다시 .InNamedScope()와 결합됩니다 DefinesNamedScope()와 결합하고 주입 된 IRootScope 얻을 수있다 아니라 하나 개의 클래스 ActualRoot. 이것에 대한 나쁜 점은, 대신에 을 ActualRoot에 삽입해야한다는 것입니다.

는 지금까지 내가 기억하는, 당신이 대신 할 수있는 일이며, 다음과 같이

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

한 다음이를 검색 :

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

이 방법 당신은 DefinesNamedScope() 필요하지 않습니다.

+2

당신의 솔루션은 매력처럼 작동합니다. 정말 고마워요! 두번째 제안 ('IBindingRoot.Bind (). () .WithParameter (new NamedScopeParameter (scopeName));')가 작동하지 않으므로 응답에서 제거하겠다는 자유를 얻었다. – jeyk

관련 문제