2012-02-14 21 views
5

我正在嘗試Ninject,並且正在修改我用Structure Map編寫的代碼以查看它是多麼容易。在這個基本代碼中,我有一個通過結構映射註冊表具有不同配置的對象圖,並且在運行時通過數據庫中的值選擇要使用的對象(在這種情況下,注入一些對象來撤回wcf服務主體) 。例如(使用結構圖代碼):使用名稱來區分使用IoC的實例

註冊表1設置IBusinessContext,IRules和ILogger類型的所有默認值。這只是將GenericContext/Logger/Rules類型添加到接口中而沒有其他專業化。

public GenericRegistry() 
    { 
     // Set up some generic bindings here 
     For<ILogger>().Use<Loggers.GenericLogger>(); 
     For<IBusinessRule>().Use<Rules.StandardRule>(); 
     For<IBusinessContext>().Use<Contexts.GenericBusinessContext>(); 
     For<ILoggerContext>().Use<Loggers.GenericLoggerContext>(); 
    } 

註冊2臺達IBusinessContext使用SpecialisedContext類,並告訴使用SpecializedLogger的構造函數。 IBusinessContext的實例名爲「SpecializedContext」。

public SpecializedRegistry() 
    { 
     // Old style syntax as it affects the default for IBusinessContext 
     // Perhaps a hint at what I'm doing? 
     InstanceOf<IBusinessContext>().Is.OfConcreteType<Contexts.SpecializedBusinessContext>().Named(SpecializedInstanceName).Ctor<ILogger>().Is<Loggers.SpecialisedLogger>(); 
    } 

這一切都按預期的方式在結構圖中工作(取決於舊的或新的語法)。

但是,當我使用Ninject時,我遇到了一個問題,期望未命名的實例是默認的(不是Ninject如何工作,我知道)。這導致了一些研究,這些研究都表明使用命名實例是一個非常糟糕的想法。我知道有更好的方法來做到這一點,使用自動註冊或屬性來設置一個名稱或請求某種類型,但在我所描述的系統中,需要有一種方法來在運行時找出要求的配置在樹的頂部(並且讓IoC框架根據註冊類型或規則找出其餘部分)。

所以......我剛剛使用IoC概念錯誤在這裏期望按名稱詢問我的頂級對象,或者通常有更好的方法來做我想做的事情嗎?我是否應該使用像MEF這樣的東西,並將其全部像插件一樣對待?

我強調我沒有像這樣使用啞工廠,並在代碼的每個級別詢問容器中類型爲x的實例,它僅僅是啓動操作。

預先感謝您的時間和幫助:)

回答

3

沒有什麼所有的錯名字,設立ninject綁定,如果這是實現它是什麼,你需要IMO的唯一途徑。

所以基本語法是:

Bind<IBusinessContext>().To<ConcreteBusinessContext>().Named("XYZ"); 

或者,如果你需要一個特定調用類來獲得一個不同的結合,那麼你可以嘗試:

Bind<IIBusinessContext>().To<SomeOtherConcreteBusinessContext>().WhenInjectedInto<TypeOfCallingClass>(); 

但是,如果調用類(我對於在其ctor中具有IBusinessContext的類提供的配置值提供了一個確定要加載的具體類型的配置值,那麼您將需要使用代理:

Bind<Func<string, IBusinessContext>>().ToMethod(ctx => str => DetermineWhichConcreteTypeToLoad(ctx, str)); 

//messy sudo code 
static DetermineWhichConcreteTypeToLoad(IContext ctx, string str) 
{ 
    if(str == "somevalue"){ 
     return ctx.Kernel.Get<ConcreteType1>(); 
    else 
     return ctx.Kernel.Get<ConcreteType2>(); 
} 

和您的調用類看起來像:

class DoStuff 
{ 
    Func<string, IBusinessContext>> contextFunc; 

    DoStuff(Func<string, IBusinessContext>> contextFunc) 
    { 
     this.contextFunc = contextFunc; 
    } 

    void SomeMethod() 
    { 
     var configuredValue = GetConfiguredValueSomehow(); 
     var context = contextFunc(configuredValue); //<-- this passes your config value back to ninject in the ToMethod() lambda 
     //do something with context 
    } 
} 

在那個例子中,沒有必要命名實例,因爲你有加載特定的具體類型的方法,但你仍然可以,如果使用命名實例你想要做這樣的事情:

Bind<IBusinessContext>().To<ConcreteBusinessContext>().Named("config1"); 
Bind<IBusinessContext>().To<SomeOtherBusinessContext>().Named("config2"); 

Bind<Func<string, IBusinessContext>>().ToMethod(ctx => str => ctx.Kernel.Get<IBusinessContext>().Named(str)); 

class DoStuff 
{ 
    Func<string, IBusinessContext>> contextFunc; 

    DoStuff(Func<string, IBusinessContext>> contextFunc) 
    { 
     this.contextFunc = contextFunc; 
    } 

    void SomeMethod() 
    { 
     var configuredValue = "config1"; 
     var context = contextFunc(configuredValue); //<-- this will passthrough "config1" to the above ToMethod() method and ask for a IBusinessContext named "config1" 

    } 
} 

編輯:我忘了提,如果你的配置值不必須來自調用代碼,然後這使得事情變得更加簡單。您的代碼可以代替看起來像:

// this method can just be a global method in you app somewhere 
static string GetConfigValue() 
{ 
    //something like 
    return AppSetting.Get("config"); 
} 

Bind<IBusinessContext>().To<ConcreteBusinessContext>().When(r => GetConfigValue() == "config1"); 
Bind<IBusinessContext>().To<SomeOtherBusinessContext>().When(r => GetConfigValue() == "config2"); 

class DoStuff 
{ 
    IBusinessContext context; 

    DoStuff(BusinessContext context) 
    { 
     this.context = context; 
    } 

    void SomeMethod() 
    { 
     //use the context value as you normally would 
    } 
} 

可以發揮創造性而非使用魔法字符串,你的配置方法可以加載一個枚舉和你當()方法可以測試平等對抗的枚舉,而不是字符串,但你明白了。這在ninject中被稱爲上下文綁定,我可以告訴你這個曾經是SM的狂熱用戶,這比SM的任何東西都強大得多。檢查When()方法的其餘部分,看看你能做什麼。

+0

謝謝Aaron!這爲我清除了一些東西:)非常感謝。 – NoodleAwa 2012-02-15 14:58:37

相關問題