2012-03-22 24 views
5

Aşağıdaki kod var: Yapıcı enjeksiyonu ileParametre olarak `Func <>` olan bir sınıf nasıl kaydedilir?

_container = new UnityContainer(); 
_container.RegisterType<IDownloader, Downloader>(); 
_container.RegisterType<INewObject, NewObject>(); 
_container.RegisterType<SearchViewModel>(); 

SearchViewModel sınıfı:

class SearchViewModel 
{ 
    private readonly Func<IDownloader> _downloaderFactory; 
    private readonly INewObject _newObject; 
    private IDownloader _downloader; 

    public SearchViewModel(Func<IDownloader> downloaderFactory, INewObject newObject) 
    { 
     _downloaderFactory = downloaderFactory; 
     _newObject = newObject; 
    }   
} 

soru: nasıl parametre olarak Fun<> sahiptir SearchViewModel kayıt?

_container.RegisterType<SearchViewModel>(new InjectionConstructor(DownloaderFactory())); 

Yukarıdaki kod sadece INewObject olmadan çalışır.

hedefi: Çöz InjectionConstructor ile fabrika ve otomatik INewObject, INewObject2, INewObject3 çözmek (gibi parametreler olmadan: RegisterType<SearchViewModel>()).

Mümkün mü? Belki de alternatifler?

public interface IDownloaderFactory 
{ 
    IDownloader Create(); 
} 

Sonra sadece örneklerini çözmek için tekrar kabı kullanan fabrikayı temsil edecek bir sınıf oluşturmak

:

+1

Neden INewObject parametreleri için Setter enjeksiyonu kullanmıyorsunuz? – daryal

+0

Neden SearchViewModel'i Func 'a bağımlı hale getiriyorsunuz? Sızan soyutlama değil mi? IDownloader arayüzünü doğrudan enjekte etmeniz gerektiğini düşünüyorum. IDownloader'ın beton uygulaması fabrika davranışını kapsülleyebilir. Buradaki kod örneğine bakın: http://stackoverflow.com/questions/9757953/can-any-of-existing-ioc-containers-create-the-lazy-proxy-classes-dynamically –

cevap

8

Ben problemini çözdük: Denedim önce çünkü

_container.RegisterType<Func<IDownloader>>(new InjectionFactory(i => 
      new Func<IDownloader> (() => _container.Resolve<IDownloader>()))); 
_container.RegisterType<SearchViewModel>(); 

yeni Func, bir anahtardır: Ayrıca

_container.RegisterType<Func<IDownloader>>(new InjectionFactory(i => 
      _container.Resolve<IDownloader>())); 

IDownloaderFactory yerine Func<IDownloader> downloaderFactory kullanmak daha iyi bir yol. IDownloaderFactory, temsilci kapsülleyebilir. Aynı zamanda bir delege fabrikanın içinde bağımlılık olarak kullanılmasının, kırık Kompozisyon Kökünden daha iyi bir çözüm olduğunu düşünüyorum.

2

burada kullanılacak genel kabul görmüş desen soyut fabrika beyan ve biraz daha açık hale getirmektir:

public class DownloaderFactory : IDownloaderFactory 
{ 
    private UnityContainer _Container; 
    public DownloaderFactory(UnityContainer container) 
    { 
     this._Container = container; 
    } 

    public IDownloader Create() 
    { 
     return this._Container.Resolve<IDownloader>(); 
    } 
} 

Bu yaklaşımı kullanarak daha açık ve, konteynerle daha güzel oynar da yine şimdi sadece SearchViewModel sınıfına küçük düzenleme gereken, uzak uygulama ve iş mantıktan kabı tutar:

class SearchViewModel 
{ 
    private readonly IDownloaderFactory _downloaderFactory; 
    private readonly INewObject _newObject; 

    public SearchViewModel(IDownloaderFactory downloaderFactory, INewObject newObject) 
    { 
     _downloaderFactory = downloaderFactory; 
     _newObject = newObject; 

     Console.WriteLine(downloaderFactory.Create().GetHashCode()); 
     Console.WriteLine(downloaderFactory.Create().GetHashCode()); 
    } 

}

Şimdi bunu görebilirsiniz Sadece çalışır ve her defasında yeni örneklerini oluşturur. şu şekilde görünecektir konteyner kurma

:

Eğer fabrika bu yöntemi veya ThreadLocal kullanarak aynı örneği ya alır böylece çalışıyoruz kabın örneğini kaydetmek gerekir
 var container = new UnityContainer(); 
     container.RegisterType<IDownloader, Downloader>(); 
     container.RegisterType<INewObject, NewObject>(); 
     container.RegisterType<IDownloaderFactory, DownloaderFactory>(); 
     container.RegisterType<SearchViewModel>(); 
     container.RegisterInstance(container); 
     var model = container.Resolve<SearchViewModel>(); 

Bildirimi instancing ya da bir şey.

Not: da sadece Func yaklaşım kullanarak veya downloader çözmek için konteyner kullanarak istemci istenmeyen etkilere neden olabilir gerçeği konusunda dikkatli olun. Örneğin, kapsayıcı varsayılan olarak Downloader nesnelerine geçici olarak ayarlanmışsa, her seferinde yeni bir örnek oluşturulur. Kapsayıcıdaki ömrünü değiştirmek istemcinin her defasında aynı örneği almasına neden olabilir. Böyle bir durumda, indirici nesneyi fabrikada elle oluşturmak ve kabı yalnızca indiricinin argümanları için kullanmak daha iyidir.

İlgili konular