2011-12-22 83 views
1

免責聲明:我對DI和IoC相當陌生,請原諒任何激烈的誤解。提供Ninject與構造函數依賴它不能解決?

考慮一個ClassB,它需要一個實現IClassA的對象。 Ninject應該能夠注入的ClassA情況下進入ClassB構造,假設它可以構建的ClassA實例:

public class ClassA : IClassA 
{ 
    public ClassA(string runtimeDependency) { /* ... */ } 
} 

public class ClassB : IClassB 
{ 
    public ClassB(IClassA depA) { /* ... */ } 
} 

public sealed class TestBootstrapModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IClassA>().To<ClassA>(); 
     Bind<IClassB>().To<ClassB>(); 
    } 
} 

現在,讓我們說一些運行時的邏輯參與獲得提供給ClassAstring runtimeDependency。我應該如何向Ninject提供runtimeDependency,以便它可以提供ClassB的實例ClassA

該字符串只會被確定一次,所以我不需要擔心爲每個實例注入新值。

回答

2

一個方式這樣做是通過一種方法提供ClassA。另外請記住,使用Ninject 2,您不需要模塊,並且可以直接在內核中執行綁定。

Bind<IClassA>().ToMethod(_ => 
    { 
    // do something interesting with a runtimeDependancy 
    return new ClassA(someInterestingVariable); 
    }); 

我真的採取了刺來當你運行時變量可用,它的範圍。

+0

我很高興你提到變量的生命期和範圍;如果變量在綁定時不存在,該怎麼辦? (我相信我應該儘早初始化我的所有綁定並在一個共同的位置。) – Rob 2011-12-29 02:49:36

+1

@robjb:這似乎更像是一個設計問題,而不是一個ninject。沒有更多的上下文,這很難說。你只需要確定一次字符串,所以它很可能需要你在設置之後做* all *你的綁定。請記住,我絕不是Ninject的專家。 – Marc 2012-01-02 14:05:38

0

這裏有幾個選項取決於您的設計和具體問題。首先,最簡單的解決方法就是提供價值,當你從Ninject

Kernel.Get<IClassA>("runtimeDependencyValue"); 

請求您的服務。然而,如果事情變得更加有趣,這是不可能的。我之前解決這個問題的方法是實際創建System.String本身的上下文綁定。

說,如果我要綁定一個連接字符串,我將創建一個自定義屬性:

[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple = false, Inherited = true)] 
public class ConnectionStringAttribute : Attribute  
{ 
    /// <summary> 
    /// Denotes the setting that you want to populate the given property with. 
    /// </summary> 
    public string SettingName { get; private set; } 

    public ConnectionStringAttribute(string configSettingName = "") 
    { 
     SettingName = configSettingName; 
    } 
} 

,然後我裝飾我的服務的構造是這樣的:

public class ClassA : IClassA 
{ 
    public ClassA([ConnectionString("AppDB")] string runtimeDependency) { /* ... */ } 
} 

最後,我結合將看起來像這樣:

Bind<string>() 
    .ToMethod(ctx => 
    { 
     var attr = (ConnectionStringAttribute)context.Request.Target.GetCustomAttributes(typeof(ConnectionStringAttribute), true).First(); 
     string settingName = string.IsNullOrEmpty(attr.SettingName) ? context.Request.Target.Name : attr.SettingName; 
     return ConfigurationManager.ConnectionStrings[settingName].ConnectionString; 
    }) 
    .WhenTargetHas<ConnectionStringAttribute>(); 

你明白了。希望這有助於:)