2016-11-29 1 views
0

내 접근 방식이 완전히 잘못되었을 수도 있지만 해결을 시도하기 전에 실제 요구 사항을 먼저 설명하고 싶습니다. 내 접근 방식은 제공된 세부 정보를 기반으로합니다 here열거자를 기반으로 함축을 반환하는 Ninject

작업 : 마법사 기반 구조에서 현재 단계를 기준으로 BaseWizardStepNavigator 개체를 가져옵니다. 예 : 단계 WizardStep.Step1에있는 경우 Step1Navigator의 인스턴스를 반환합니다. Step1Navigator의 인스턴스에는 해당 생성자에서 제공되는 삽입 된 어셈블리가 있어야합니다.

public class Step1Navigator : BaseWizardStepNavigator 
{ 
    private readonly ISomeReader _reader; 
    public Step1Navigator(ISomeReader reader) 
     : base(WizardSteps.Step1) 
    { 
     _reader = reader; 
    } 
} 

... 해당 인수 reader이 적절한 구현으로 채워집니다.

제 생각에는 ninject가 기본 클래스의 모든 구현을 (적절한 IoC 주입과 함께) 전달하여 인스턴스를 생성 할 수있는 관리자 객체가 있다고 생각합니다.

public class NavigatorManager 
{ 
    private readonly List<BaseWizardStepNavigator> _navigators; 
    public class NavigatorManager(IEnumerable<BaseWizardStepNavigator> navigators) 
    { 
     _navigators = new List<BaseWizardStepNavigator>(navigators); 
    } 
    public BaseWizardStepNavigator Get(WizardStep step) 
    { 
     return _navigators.FirstOrDefault(n => n.Step == step); 
    } 
} 

결국 다음 단계가 무엇인지 결정하기 위해 적절한 네비게이터와 마법사 단계의 10 년대가있을 것이다 그러나 그들은 그렇게 때때로 DB를 공격해야합니다.

현재 Ninject와 Ninject.Conventions를 사용중인 NinjectModule에서 바인딩을 수행하려고합니다.

모듈 (로드 방법);

Kernel.Bind(s => s.FromAssemblyContaining(typeof(BaseWizardStepNavigator)) 
        .SelectAllClasses() 
        .WhichAreNotGeneric() 
        .InheritedFrom<BaseWizardStepNavigator>() 
        .BindWith<NavigatorBinding>()); 
var test = Kernel.GetAll<BaseWizardStepNavigator>(); 

그런 다음 바인딩 및 공급자에 대한 다른 클래스. kernel.GetAll<BaseWizardStepNavigator>()에 대한 호출이 Provider 구현 메소드를 호출 않지만

public class NavigatorBinding : IBindingGenerator 
{ 
    public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot) 
    { 
     if (type.IsInterface || type.IsAbstract) 
     { 
      yield break; 
     } 

     yield return bindingRoot.Bind(typeof(BaseWizardStepNavigator)).ToProvider<NavigatorProvider>(); 
    } 
} 

public class NavigatorProvider : IProvider<BaseWizardStepNavigator> 
{ 
    public object Create(IContext context) 
    { 
     return null; 
    } 

    public Type Type { get { throw new NotImplementedException(); } } 
} 

지금, 나는 실제로 개체를 다시 침을 얻을하는 방법으로 손실 조금 있어요. 문서가 애매하고 나는 올바른 경로에 있다고 확신하지는 않습니다. 도움?

+0

관리자가 생성자에서 탐색기 목록을 가져 오더라도 WizardStep에 따라 반환 할 대상을 결정하는 방법은 무엇입니까? 스텝과 핸들러 사이에 어떤 종류의 맵이 필요한 것처럼 보입니다. – JuanR

+0

@Juan 나는 위의 예에서 그것을 포함하지 않았지만있다. 'BaseWizardStepNavigator' 생성자는 각 자식이 지정해야만하는'WizardStep' 인수를 취합니다. 'Get()'메서드에서'if (manager.Step == step) return manager;'를 할 수 있습니다. 문제는'IProvider' 구현입니다. 적절한 오브젝트를 선택하여 반환하는 방법을 모르겠습니다. – DiskJunky

+0

클래스를 식별하는 단계 대신 인터페이스를 사용하면 훨씬 간단 해집니다. DI 컨테이너를 사용하고 있으므로 각 단계마다 인터페이스를 만들고 컨테이너에 클래스를 연결하면됩니다. – JuanR

답변

0

나는 결국 간단하게 작동하는 구현체를 얻을 수 있었다. IBindingGenerator 또는 구현이 필요하지 않았습니다.

Step1NavigatorNavigatorManager에 대한 코드는 동일하게 유지됩니다.

NinjectModule 바인딩 코드가로 변경됩니다.

// set the navigator bindings 
Kernel.Bind(s => s.FromAssemblyContaining(typeof(BaseWizardStepNavigator)) 
        .SelectAllClasses() 
        .WhichAreNotGeneric() 
        .InheritedFrom<BaseWizardStepNavigator>() 
        .BindAllBaseClasses() 
        .Configure(c => c.InRequestScope()) 
       ); 

// pass in all children of BaseWizardStepNavigator to the manager instance 
Bind<NavigatorManager>().ToSelf() 
         .InRequestScope() 
         .WithConstructorArgument(typeof(IEnumerable<BaseWizardStepNavigator>), 
                n => n.Kernel.GetAll<BaseWizardStepNavigator>()); 

.InRequestScope()은 웹 응용 프로그램에만 적용됩니다. 자신의 코드에서 .InSingletonScope() 등을 사용하는 경우 적절하게 변경하십시오.

관련 문제