2016-11-29 82 views
0

完全可能我的方法不正確,但我想在我嘗試解決問題之前先列出實際要求。我的方法基於提供的詳細信息hereNinject基於枚舉數返回實現

任務:在面向嚮導的結構中,根據當前步驟獲取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偶爾這樣做。

我目前的嘗試和執行綁定在NinjectModule我在使用Ninject和Ninject.Conventions是;

模塊(加載方法);

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

然後其他類的綁定和提供者;

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

現在,當調用kernel.GetAll<BaseWizardStepNavigator>()並調用Provider實現方法,我有點失去了對如何真正得到它吐回的對象。這些文件很模糊,我不完全確定我甚至在正確的道路上。幫幫我?

+0

即使您的Manager在其構造函數中獲取了導航器列表,如何根據WizardStep確定要返回哪個導航器?它看起來像你需要一個步驟和處理程序之間的某種地圖。 – JuanR

+0

@Juan雖然我沒有在上面的例子中包含它。 'BaseWizardStepNavigator'構造函數接受每個孩子必須指定的'WizardStep'參數。在Get()方法中,我可以執行'if(manager.Step == step)return manager;'。問題是'IProvider'的實現。我不知道如何讓它選擇並返回適當的對象 – DiskJunky

+0

如果使用接口而不是步驟來識別類,這將會簡單得多。由於您使用的是DI容器,因此只需爲每個步驟創建一個接口並將該類關聯到容器中即可。 – JuanR

回答

0

我設法得到一個相當簡單的實現工作到最後。不需要IBindingGeneratorIProvider實現。

代碼爲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()特定於Web應用程序。如果您在自己的代碼中使用.InSingletonScope()等,則可以根據情況進行更改。