2011-06-02 22 views
6

bir Genel sınıf için Varsayılan & spesifik bağlamaları Ninject: Ben soyut bir sınıf var

public sealed class NewsValidator : Validator<News> 

Şimdi ben şu gibi Bağımlılık Enjeksiyon yapmak istiyorum Ninject kullanarak (bu özel kod çalışma DEĞİLDİR):

Bind<Validator<News>>().To<NewsValidator>(); 
Bind(typeof(Validator<>)).To(typeof(NullValidator<>)); 

Yani ne başarmak istediğinizi

Validator<News> 

olduğunu "NewsValidator" sınıfına bağlı olmalıdır, ancak bu sınıfın başka bir bağlı sürümü isteniyorsa,

Varsayılan Sınıf'a (NullValidator) bağlı olması gereken
Validator<Article> 
Validator<SomethingElse> 

. Yukarıda kullanılan kodun kullanılması, bir istisna atar, çünkü, Validator < Haberler >'i hem NewsValidator hem de NullValidator'a bağlar.

Bunu nasıl uygulayabilirim? Genel sınıfın belirli türleri bireysel sınıflara bağlı olmalıdır. Açıkça bağlı olmayan genel sınıfın diğer tüm türleri, varsayılan bir sınıfa bağlanmalıdır.

Birkaç öneriden gerçekten memnun olurum! Teşekkürler!

cevap

9

IMissingBindingResolver özel bir uygulama oluşturabilirsiniz.

Çekirdek, istenen hizmet için bir bağlamayı çözümlemediği zaman, HandleMissingBinding yöntemine temsil eder (bu, KernelBase'dan türetilen herhangi bir çekirdek için geçerlidir). İstenen hizmet için bir bağ oluşturabilirse, HandleMissingBinding yöntemi her eksik bağlayıcı çözümleyiciden isteyecektir. Varsa çözücüler tarafından döndürülen bağlamalar, çekirdeğe eklenecektir.

Eksik bir bağlayıcı çözümleyici tarafından oluşturulan herhangi bir bağlamanın, çekirdeklere dolaylı olarak bir bağlayıcı olarak ekleneceğini unutmayın. Bu, uygulamanızda bir ima olabilir. Örneğin, bir hizmet için açık ve örtülü bağlamaları bir karışımınız varsa, bu bağlamaları çözme, yani kernel.GetAll<TService>(), yalnızca açık bağları çözer. Ancak, tüm bağlamalar örtük ise, hepsi çözülür.

en boş doğrulayıcıları için özel çözümleyicinizi uygulamak edelim:

Ninject IMissingBindingResolver iki standart uygulamaları bulunmaktadır. Şimdi aşağıdaki test (xUnit.net kullanılarak)

public class MissingValidatorResolver : NinjectComponent, IMissingBindingResolver 
{ 
    public IEnumerable<IBinding> Resolve(
     Multimap<Type, IBinding> bindings, IRequest request) 
    { 
     var service = request.Service; 
     if (!typeof(IValidator).IsAssignableFrom(service)) 
     { 
      return Enumerable.Empty<IBinding>(); 
     } 

     var type = service.GetGenericArguments()[0]; 
     var validatorType = typeof(NullValidator<>).MakeGenericType(type); 

     var binding = new Binding(service) 
     { 
      ProviderCallback = StandardProvider.GetCreationCallback(validatorType) 
     }; 

     return new[] { binding }; 
    } 
} 

geçer.

[Fact] 
public void ShouldResolveNonBoundValidatorDerivedFromValidatorAsNullValidator() 
{ 
    var kernel = new StandardKernel(); 
    kernel.Components.Add<IMissingBindingResolver, MissingValidatorResolver>(); 

    var validator = kernel.Get<Validator<Article>>(); 
    Assert.IsType<NullValidator<Article>>(validator); 
} 
+0

whoa :) İnanılmaz, bu bir çekicilik gibi çalışıyor. Bunu nasıl bildin?! Google bile "IMissingBindingResolver" için arama yaparken pek bir şey bulamıyor.Her neyse, bu kesinlikle mükemmel, çok teşekkürler! – Oliver