dürüst olmak gerekirse, yapıcı içinde türlerini çözmek için ilkel veya sabit olan bir sınıf tasarıma sahip olması önlemek için çalışacağını söyledi. Zaten Tavares' cevabını gördüğümüz gibi, yapılandırma çok kırılgan olur konum (güncelleme: Tavares bana net olmaması nedeniyle onun cevabını kaldırdık görünüyor). Derleme zamanı desteğini kaybedersiniz ve bu yapıcıya yapılan her değişiklik DI yapılandırmanızı değiştirmenizi sağlar.
Bunu önlemek için tasarımı değiştirmek için birden fazla yolu vardır. Hangisi size uygun olduğunu size kalmış, ama burada birkaç fikir:
Seçenek 1: değişmez bir yapılandırma DTO kullanın:
private sealed class LoginManagerConfiguration
{
public Uri Login { get; private set; }
public Uri Target { get; private set; }
public string MainRegionName { get; private set; }
public LoginManagerConfiguration(Uri login, Uri target, string mainRegionName)
{
this.Login = login;
this.Target = target;
this.MainRegionName = mainRegionName;
}
}
Şimdi izin edebilirsiniz LoginManager
bir bağımlılık almak LoginManagerConfiguration
:
public LoginManager(IRegionManager regionManager,
IEventAggregator eventAggregator,
LoginManagerConfiguration configuration)
{
...
}
LoginManagerConfiguration
basitçe böyle kaydedilebilir:
0 yerine bu tip spesifik DTO Uygulama çaplı yapılandırma nesne belirtmek için cazip olabilir, ama bu bir tuzak. Bu tür uygulama çapında yapılandırma nesnesi, Service Locator anti-pattern'in yapılandırma eşdeğeridir. Bir türün hangi konfigürasyon değerlerini gerektirdiği belirsizleşir ve sınıfları test etmek zorlaşır.
Seçenek 2: Sadece DI konfigürasyonu amacıyla, bu sınıfın
Diğer bir seçenek bu sınıftan türetmek olduğunu türevi. Bu sınıf imzasını değiştiremezsiniz zaman özellikle yararlıdır (yani bir üçüncü taraf bileşen olduğunda):
private sealed class DILoginManager : LoginManager
{
DILoginManager(IRegionManager regionManager,
IEventAggregator eventAggregator)
: base(regionManager, eventAggregator,
ConfigurationManager.AppSettings["MainRegion"],
new Uri("Login"),
new Uri("Target"))
{
...
}
}
başvurunuzun kompozisyon köküne yakın bu sınıfı tanımlayın.Bu sınıf, DI yapılandırmanızın bir uygulama ayrıntısı haline gelir. türünüze tescili artık çok basit olacaktır:
container.RegisterType<ILoginManager, DILoginManager>();
çağrıları ile Ama çok dikkatli olun böyle ConfigurationManager.AppSettings["MainRegion"]
tembel yük yapılandırma değerleri,. Bu, yapılandırma hatalarının uygulama başlangıcı sırasında yakalanmadığı durumlara kolayca yol açabilir, ki bu gerçekten tercih edilir.
Seçenek 3: kullanın fabrika temsilci
ben sunmak istiyorum son seçenek bir fabrikasıdır. Bu Traveses'in cevabı gibi görünecek, fakat daha güvenlidir:
var mainRegion = ConfigurationManager.AppSettings["MainRegion"];
container.Register<ILoginManager>(new InjectionFactory(c =>
{
return new LoginManager(
c.Resolve<IRegionManager>(),
c.Resolve<IEventAggregator>(),
ConfigurationManager.AppSettings["MainRegion"],
new Uri("Login"),
new Uri("Target"));
}));
Umarım bu yardımcı olur.
InjectionFactory yaklaşımı için, Func türlerini, bu parametreleri kabul eden ve bu şekilde bir ILoginManager döndüren bir InjectionFactory ile ilişkilendirmeniz için yazabilirsiniz: yeni InjectionFactory (c => (login, target) , mainRegionName) => c. öğesini (yeni ParameterOverride ("mainRegionName", mainRegionName), yeni ParameterOverride ("login", login), yeni ParameterOverride ("target", target)))) çözümleyin. Çözümü bu şekilde yaparak, bağımlılarınız için kurucunuzda esnek kalırsınız ve sadece ilkel parametre değişiklikleri için değiştirmek zorunda kalırsınız. –
Çok güzel cevap, btw. –
Eklemek için şunu ekleyin: kullanım bağımlılık olarak bir Func kabul edersiniz ve bu parametreleri ILoginManager verecek olan işleve iletirsiniz. Eğer bu ayarlarsa, Steven'ın yaklaşımına sadık kalacağım, ama eğer belirli bağlamlarda değişebilen çalışma zamanı değerleriyse, böyle bir şey yapmanız gerekebilir. –