2013-07-24 8 views
5

का दृष्टांत को चयन करने के लिए एक enum का उपयोग मैं एक enum कि मैं डीटीओ के लिए संबद्ध करने के लिए कोशिश कर रहा हूँ है:जो वर्ग

public enum DtoSelection 
{ 
    dto1, 
    dto2, 
    dto3, 
} 

इस enum में 108 और मूल्यों हैं।

मैं इन डीटीओ के प्रत्येक के लिए एक डीटीओ वस्तु है:

public class dto1 : AbstractDto 
{ 
     public int Id { get; set; } 
     //some stuff specific to this dto 
} 

मैं एक विधि (अंत में एक सेवा) है कि मुझे डीटीओ से जुड़े प्रकार का कोई नया डीटीओ वस्तु वापस आ जाएगी बनाने के लिए कोशिश कर रहा हूँ प्रश्न में:

private AbstractDto(int id) 
{ 
     if (id == DtoSelection.Dto1.ToInt()) //extension method I wrote for enums 
      return new Dto1(); 
     if (id == DtoSelection.Dto2.ToInt()) 
      return new Dto2(); 
} 

स्पष्ट रूप से मैं यह 108 बार नहीं करना चाहता हूं। किसी भी कारण से मेरा दिमाग बस कुछ स्पष्ट याद कर रहा है। इसे संभालने का सबसे अच्छा तरीका क्या है।

+0

यदि यह संभव है तो मैं उत्सुक हूं – Jonesopolis

+0

सबसे पहले आप 'स्विच' का उपयोग कर अपनी' if' सूची में सुधार कर सकते हैं। और क्या आप प्रतिबिंब का उपयोग करना चाहते हैं? –

+1

एक enum में 108 विभिन्न डीटीओ वस्तुओं के पीछे तर्क क्या है? एक सरणी का उपयोग क्यों नहीं करते? – chancea

उत्तर

3

इस वर्ग तुम क्या चाहते हो जाएगा जब तक डीटीओ वर्गों को उसी नामस्थान में परिभाषित किया जाता है, जैसे कि सार सार (आपको इसे ट्विक करने की आवश्यकता होगी):

निम्नलिखित enums को देखते हुए और वर्गों:

public enum DtoSelection 
{ 
    Dto1, 
    Dto2, 
    Dto3, 
} 

public abstract class AbstractDto 
{ 
} 

public class Dto1 : AbstractDto 
{ 
} 

public class Dto2 : AbstractDto 
{ 
} 

public class Dto3 : AbstractDto 
{ 
} 

इस विधि उन्हें हल होगा:

public static class DtoFactory 
{ 
    public static AbstractDto Create(DtoSelection dtoSelection) 
    { 
     var type = Type.GetType(typeof(AbstractDto).Namespace + "." + dtoSelection.ToString(), throwOnError: false); 

     if (type == null) 
     { 
      throw new InvalidOperationException(dtoSelection.ToString() + " is not a known dto type"); 
     } 

     if (!typeof(AbstractDto).IsAssignableFrom(type)) 
     { 
      throw new InvalidOperationException(type.Name + " does not inherit from AbstractDto"); 
     } 

     return (AbstractDto)Activator.CreateInstance(type); 
    } 
} 
4

Activator.CreateInstance विधि का उपयोग करें और इसे enum's ToString मान पास करें।

Type type = Type.GetType(DtoSelection.dto1.ToString()); 
var temp = Activator.CreateInstance(type); 
+0

मुझे यह पसंद है। हालांकि मुझे प्रत्येक डीटीओ के लिए यह 108 बार करना होगा। – Robert

+0

@Robert, आप अपने enum के सदस्यों पर एक लूप प्राप्त कर सकते हैं और फिर उदाहरण बना सकते हैं और इसे सूची में जोड़ सकते हैं, लूपिंग देखने के लिए: http://stackoverflow.com/questions/972307/can-you-loop-through-all- enum-values ​​ – Habib

1

मैं funcs के शब्दकोश का उपयोग करता हूं।

Dictionary<DtoSelection, Func<AbstractDto>> dictionary = 
     new Dictionary<DtoSelection, Func<AbstractDto>> 
{ 
    {DtoSelection.dto1,() => new dto1()} 
}; 

var dto = dictionary[DtoSelection.dto1](); 
+0

मैं 108 बार लिखने से बचने की कोशिश कर रहा हूं। मुझे सभी प्रकार के शब्दकोश का निर्माण करने की आवश्यकता होगी। – Robert

1

Activator.CreateInstance उपयोग करके देखें:

return (AbstractDto)Activator.CreateInstance 
         (Type.GetType(((DtoSelection)id).ToString(), true, true); 

या वैकल्पिक रूप से, एक धोखा का एक सा, तो आप इस के लिए कुछ कोड पीढ़ी का उपयोग कर सकते हैं:

public static string GenerateValues() 
{ 
    StringBuilder sb = new StringBuilder(); 
    sb.AppendLine("DtoSelection selection = (DtoSelection)id;"); 
    sb.AppendLine("switch (selection)"); 
    foreach (DtoSelection value in (DtoSelection[])Enum.GetValues(typeof(DtoSelection)) 
    { 
     sb.AppendLine("case DtoSelection." + value.ToString() + ":"); 
     sb.AppendLine("return new " + value.ToString() + ";"); 
    } 
} 
0

आप एक आईओसी कंटेनर का उपयोग करना चाहिए (एकता, StructureMap, Ninject ...)

आईओसी की अनुमति देता है के लिए:

  • नाम के साथ एक प्रकार रजिस्टर, तो (जैसे कंटेनर पर निर्भर करता है):

    Container.Register<AbstractDto,Dto1>(DtoSelection.dto1.ToString()); 
    
  • प्रकार

    Container.Resolve<AbstractDto>(DtoSelection.dto1.ToString()); 
    

यह आपके लिए इन्स्टेन्शियशन के सभी विवरण संभाल लेंगे समाधान करें।

प्रस्तावित अन्य समाधानों को "गरीब आदमी का आईओसी" कहा जाता है। पहिया को पुन: पेश न करें।यदि आप "निर्माता इंजेक्शन" का उपयोग हटाया जा सकता है new() बाधा (requirement of parameterless constructor):

public void RegisterDto<TDto>(DtoSelection dtoSelection) 
    where TDto : AbstractDto, new() 
    { 
    Container.Register<AbstractDto,Dto1>(dtoSelection.ToString()); 
    } 


    public TDto GetDto<TDto>(DtoSelection dtoSelection) 
    where TDto : AbstractDto 
    { 
    return Container.Resolve<AbstractDto>(dtoSelection.ToString()) as TDto; 
    } 

नोट:

बेशक, आप तरीकों के पीछे कंटेनर को छिपाने चाहिए। कन्स्ट्रक्टर इंजेक्शन उन मानों को पंजीकृत करने की अनुमति देता है जिन्हें पैरामीटर के साथ कन्स्ट्रक्टर के पैरामीटर के रूप में उपयोग किया जाएगा। यह पैरामीटर अन्य ऑब्जेक्ट्स या अमूर्त ऑब्जेक्ट्स (इंटरफेस, एबस्ट्रैक क्लासेस) हो सकता है। इस काम के लिए आपको इस पैरामीटर को contianer में पंजीकृत करने की आवश्यकता है।

जो भी आईओसी आप चुनते हैं, उसके "गरीब आदमी के आईओसी" पर बहुत सारे फायदे होंगे।

अद्यतन

आप इसे लिखने में कई बार से बचना चाहते हैं, सबसे आईओसी कंटेनर भी नाम से रजिस्टर करने के लिए अनुमति देते हैं, तो आप इस तरह पंजीकरण कर सकते हैं:

// iterate the DtoSelection Enum 
    foreach(var e in Enum.GetValues(DtoSelection)) 
    { 
    DtoSelection dtoSel = (DtoSelection)e; 
    int n = (int)dtoSel; 
    Container.Register<AbstractDto>("Dto" + n, dtoSel.ToString()); 
    } 

नोट: पहला पैरामीटर प्रकार का नाम (या पूर्ण प्रकार का नाम) है। दूसरा वह नाम है जो इसे हल करने की अनुमति देगा।

+1

यह ओवरकिल है, आईएमओ। –

+0

@newStackExchangeInstance क्यों overkill? आपको सरल रूप से एक Nuget पैकेज जोड़ना होगा, और कोड की कुछ पंक्तियां लिखनी होंगी, अगर आप अपने "गरीब आदमी के आईओसी" लिखते हैं। इसके अलावा आप गलतियों को करने या नट-किरकिरा विवरण भूलने से बचें। यह अधिक सुरक्षित और कुशलतापूर्वक काम करेगा कि लगभग कुछ भी जिसे आप कार्यान्वित कर सकते हैं। मेरे लिए ओवरकिलिंग पहले से हल की गई समस्या को हल करने के लिए पहिया को फिर से शुरू कर रहा है ... और शायद कुछ अप्रत्याशित बग पेश कर रहा है। – JotaBe

+0

चलो देखते हैं, अधिक जटिल क्या है (और इसलिए बग्गी): एक्टिवेटर। क्रिएट इंस्टेंस या एक जटिल आईओसी फ्रेमवर्क? –

0
public AbstractDto CreateDto(DtoSelection selection) 
{ 
    return (AbstractDto)Activator.CreateInstance(Type.GetType("Perhaps.Some.Qualifier.Here." + selection.ToString())); 
} 
संबंधित मुद्दे