2012-01-13 29 views
16

Sınıfın, aynı sayıda parametreye sahip iki kurucuya sahip olduğu bir birliği kullanarak bir sınıf örneği oluşturmak istiyorum. İşte Birlik kullanarak birden çok kurucu kullanarak örneği çözme

instantiation geçerli: kurucular

_unityContainer.Resolve<IGradeType>(new ParameterOverride("gradeTypeStringFromXmlFile", gradeTypeStringFromXmlFile)); 

Ve burada şunlardır: Bunu denerseniz

public GradeType(string gradeTypeStringFromXmlFile) 
    { 
     _gradeTypeStringFromXmlFile = gradeTypeStringFromXmlFile; 
    } 

    public GradeType(Enum.GradeType gradeType) 
    { 
     _gradeType = gradeType; 
    } 

ben bir istisna tipi GradeType uzunluğu 1 çoklu oluşturucusu yok söyleyerek olsun anlaşılamıyor.

Biriyle çalışmasını sağlamak için [InjectionConstructor] özniteliğini bir yapıcı üzerinde ayarlayabilirim, ancak diğer yapıcıyı kullanarak bir arada bir örnek oluşturamıyorum.

Eşit sayıda parametreye sahip birden fazla kurucuya sahip olmanın ve örnekleri oluşturmak için hala birliği kullanmanın bir yolu var mı?

+0

neden sınıf oluşturmadan önce gradeType dizesinde 'Enum.Parse' kullanılmıyor? – jgauffin

+0

sadece ClassType sınıfının dizeyi dönüştürdüğü sezgisel bir tasarım gibi hissediyor. – FatAlbert

+1

Var olmayan herhangi bir değer bir istisna atacağından veya bir hata gizleyeceğinden bana göre kırılgan bir çözüm gibi görünüyor. – jgauffin

cevap

26

Evet, Unity'ye hangi kurucuyu kullanması gerektiğini söylemek mümkündür, ancak bunu yalnızca türünüzü InjectionConstructor ile kaydettirdiğinizde yapabilirsiniz. Her iki kurucuyu kullanmak istiyorsanız, kayıtlarınızı adlandırmanız ve çözerken bu ismi kullanmanız gerektiğinden karmaşıktır. Birlik sürümü 2.1.505 ile inşa

Örnek:

var continer = new UnityContainer(); 

continer.RegisterType<IGradeType, GradeType>("stringConstructor", 
    new InjectionConstructor(typeof(string))); 

continer.RegisterType<IGradeType, GradeType>("enumConstructor", 
    new InjectionConstructor(typeof(EnumGradeType))); 

IGradeType stringGradeType = continer.Resolve<IGradeType>("stringContructor" , 
    new DependencyOverride(typeof(string), "some string")); 

IGradeType enumGradeType = continer.Resolve<IGradeType>("enumConstructor", 
    new DependencyOverride(typeof(EnumGradeType), EnumGradeType.Value)); 
+0

tam aradığım şey! Teşekkürler – FatAlbert

+1

Bir soru: Bağımlılıkları geçersiz kılarken, kapta açıkça çözüm aramak zorunda kalıyoruz? Ancak açık bir şekilde container'ı çağırmak kötü değil mi? Uygulama kodunuzda bir sorun mu var? Ooops, aslında iki soru ;-) – Legends

0

Bir kurucuyu kaldırın ve dizeyi enum'a veya tersini yapın ve kapsayıcıyı kullanarak çözün.

+0

Bir dizeyi bir numaraya gönderemezsiniz. – jgauffin

+0

Enum.Parse - dediğiniz gibi – Jason

+0

xml dizgisi enumdan tamamen farklıdır (dizgi İsveççe). Bununla birlikte, sorduğum şey, aynı sayıda parametreye sahip birden fazla kurucuya sahip olmanın ve örneklerin oluşturulması için hala birliği kullanmanın mümkün olup olmamasıdır. – FatAlbert

1

Yansıma kullanarak ve Strategy Pattern aşağıdaki alternatif bir seçenek. yöntemlerini oluşturmak için GradeType sınıfında Şimdi)

public class StringArg : ConstructorArgs 
{ 
    public string _gradeTypeStringFromXmlFile { get; set; } 

    public StringArg (string gradeTypeStringFromXmlFile) 
    { 
     this._gradeTypeStringFromXmlFile = gradeTypeStringFromXmlFile ; 
    } 
} 

public class EnumArg : ConstructorArgs 
{ 
    public Enum.GradeType _gradeType { get; set; } 

    public EnumArg (Enum.GradeType gradeType) 
    { 
     this._gradeType = gradeType ; 
    } 
} 

3:

1) markalar argümanlar

public abstract class ConstructorArgs 
{ 
} 
) farklı beton argümanlar sınıfların sıralandığında için bir temel sınıf oluşturma Yansıma için gerekli. ParseArguments, özellikleri için ve buldukları her biri için bir ardı ardına tarar, değerini SetProperty'yi kullanarak GradeType öğesinin ilgili özelliğine kopyalar.yani gerekir (zihin ilgili özellikler oluşturmak için GradeType sınıfta

 private void SetProperty(String propertyName, object value) 
     { 
      var property = this.GetType().GetProperty(propertyName); 
      if (property != null) 
       property.SetValue(this, value); 
     } 
     private void ParseArguments(ConstructorArgs args) 
     { 
      var properties = args.GetType().GetProperties(); 
      foreach (PropertyInfo propertyInfo in properties) 
      { 
       this.SetProperty(propertyInfo.Name, 
        args.GetType().GetProperty(propertyInfo.Name).GetValue(args)); 
      } 
     } 

4): Bu eşleştirme için özellik adını kullandığı için GradeType ve beton ConstructorArgs ikisinde birden aynı özellik adını tutmak önemlidir tam olarak beton ConstructorArgs kullanılan aynı isim ve türlerini kullanmak ancak tip ConstructorArgs bir parametre ile GradeType sınıf için istediğiniz herhangi bir erişim değiştirici)

public string _gradeTypeStringFromXmlFile { get; set; } 
    public Enum.GradeType _gradeType { get; set; } 

5) bir kurucu oluşturun kullanabilirsiniz:

public GradeType(ConstructorArgs args) 
    { 
     this.ParseArguments(args); 
    } 

6) Şimdi tek kurucu kullanılarak Unity GradeType kayıt olabilirsiniz ancak bunu çözmek için zaman argüman olarak farklı tipte geçirebilirsiniz:

_unityContainer.RegisterType<IGradeType, GradeType>(
     new InjectionConstructor(typeof(ConstructorArgs))); 

    var args1 = new StringArg(gradeTypeStringFromXmlFile); // string 
    IGradeType gradeType1 = _unityContainer.Resolve<IGradeType>(
     new ResolverOverride[]{new ParameterOverride("args", args1)}); 

    var args2 = new EnumArg(gradeType); // enum 
    IGradeType gradeType2 = _unityContainer.Resolve<IGradeType>(
     new ResolverOverride[]{new ParameterOverride("args", args2)}); 

art arda bir yineleme içinde türünü çözmek planlıyorsanız Bu yaklaşım ideal olmayabilir çünkü Yansıma bir performans cezasıyla birlikte gelir.

İlgili konular