2012-05-18 16 views
14

Uygulamamda kullanılan ayarları içeren bir IConfig nesnesine sahibim.Atıla: Diğer Nesnenin Mülk Yapıcı Bağlamını Bağla

public interface IConfig 
{ 
    string Username { get; } 
    string Password { get; } 
    //... other settings 
} 

public class Foo : IFoo 
{ 
    private readonly string username; 
    private readonly string password; 

    public Foo(IConfig config) 
    { 
     this.username = config.Username; 
     this.password = config.Password; 
    } 
} 

olumsuz bir genel yapılandırma dosyasından deserialised çünkü IConfig ayarlardan çok sayıda içerdiğini, bu nedenle, şu şekildedir: Şu anda ben, ihtiyacı her nesnenin kurucusu içine tüm nesne enjekte tüm nesnenin enjekte edilmesi gereksizdir. Yapmak istediğim, kurucuyu Foo(string username, string password) olarak değiştirmektir, böylece yalnızca ihtiyaç duyduğu ayarları alır. Bu aynı zamanda çok daha kolay test için Foo nesnelerinin yaratılmasını sağlar (Foo oluşturmak için IConfig kurulumuna gerek kalmaz). Benim NinjectModule doğrudan aşağıdaki gibi bir şey yapıcı argümanları bağlamak istiyorum:

public class MyModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IConfig>().To<JsonConfig>() 
      .InSingletonScope(); 

     Bind<IFoo>().To<Foo>() 
      .WithConstructorArgument("username", IConfig.Username) 
      .WithConstructorArgument("password", IConfig.Password); 
    } 
} 

Açıkçası bu kod çalışmaz

, ama ben ne istediğini yapıyor hakkında gitmek? Benim orijinal bir fikir

IKernel sonra benim IConfig nesnenin bir örneğini almak ve gerektiği gibi özelliklerini enjekte almak için NinjectModule.Kernel kullanmak, ama NinjectModule.Kernel tarafından döndürülen nesne yok Get<T>() yöntemi vardır.

cevap

14

Sen doğru yolda şunlardır: buna da modülünde mevcuttur using Ninject; ekleyerek böylece

Kernel.Get<T>() yöntem Ninject namepsace içinde ResolutionExtensions üzerinde tanımlı bir uzantısı yöntemidir.

Ama yerine Module.Kernel sen Kernel almak için WithConstructorArgument ikinci aşırı sağlanan IContext kullanmalıdır:

Bind<IFoo>().To<Foo>() 
    .WithConstructorArgument("username", 
          context => context.Kernel.Get<IConfig>().Username) 
    .WithConstructorArgument("password", 
          context => context.Kernel.Get<IConfig>().Password); 
+1

Bunu işe yaramış gibi görünmüyor. Lambda'da oluşturulan 'IConfig' nesnesi tüm varsayılan değerleri içerir (bu ayarlar için boş dizeler). Ben şimdi '' Ninject kullanarak ekledim şimdi normal bir Kernel.Get yapmak, bu düzgün çalışır. 'Bağlam' versiyonunu çalışmak için çaba sarf etmeli miyim, herhangi bir avantaj var mı? –

+0

"context.Kernel" ile çalışmalı, ona bir göz atacağım. IConfig'deki değerler nasıl öğrenilir?Birden çok çekirdek kullanıyor musunuz? – nemesv

+0

Sadece basit bir test projesi oluşturdum ve bu işe yarıyor. Benim özel çözümüme özgü bir şey olmalı. Teşekkürler! –

1

Bu Interface segregation principle için iyi bir candiate olabilir.

Bu durumda, daha sonra bu arabirimini IConfig yapmak, örneğin sadece Username ve Password özelliklerini içeren bir ICredentialConfig gibi başka bir arabirimi tanımlar.

public Interface ICredentialConfig 
{ 
    string Username { get; } 
    string Password { get; } 
} 

public Interface IConfig : ICredentialConfig 
{ 
    //... other settings 
} 

Şimdi ICredentialConfig yerine IConfig üzerine Foo bağımlı olun. Ardindan: yerine kodlanmış parametre adları sahip, Ninject kullanılarak

  1. enjekte senin JsonConfig. Foo nolu uygulama için
  2. ICredentialConfig'u gerçekleştirin/eşleştirin, tam IConfig arabirimini uygulamak yerine, testlerde eşleyin.