2011-02-25 6 views
6

मान लें, मैं इस तरह के प्रिंट विधि है:क्या अज्ञात संग्रह में मानों को पुन: स्थापित करने और मुद्रित करने के लिए एक सामान्य विधि है?

private static void Print(IEnumerable items) 
{ 
    // Print logic here 
} 

मैं इस प्रिंट विधि है, जो एक मेज की तरह सभी क्षेत्रों प्रिंट चाहिए करने के लिए एक संग्रह वर्ग पास करना चाहते हैं। उदाहरण के लिए, मेरा इनपुट संग्रह "व्यक्ति" या "ऑर्डर" या "कार" आदि हो सकता है

यदि मैं प्रिंट विधि में "कार" संग्रह पास करता हूं, तो उसे "कार" विवरणों की सूची मुद्रित करनी चाहिए जैसे कि : मेक, कलर, प्राइस, क्लास इत्यादि

मुझे रन-टाइम तक संग्रह के प्रकार को नहीं पता होगा। मैंने TypeDescriptors और PropertyDescriptorCollection का उपयोग करके समाधान का प्रयास किया और हासिल किया। लेकिन, मुझे नहीं लगता कि यह एक अच्छा समाधान है। क्या अभिव्यक्ति या जेनेरिक का उपयोग करके इसे हासिल करने का कोई और तरीका है?

+1

सबसे अच्छा आप जेनरिक के साथ कर सकते बारे में (यह मानते हुए ToString सीधे अधिरोहित नहीं है) सब कुछ कुछ 'IMyToString' इंटरफ़ेस को लागू किया है और है फिर 'IENumerable ' में लें। अन्य विधियां हैं, निश्चित रूप से, लेकिन आम तौर पर मैपिंग पर निर्भर करती हैं (टाइपकॉन्टर मैपिंग का एक रूप है) या अन्य तरीकों से आरटीटीआई का उपयोग करना। मानक polymorphism पैटर्न का सुझाव देने के लिए –

उत्तर

6

आप इस तरह प्रिंट को लागू कर सकते हैं:

static void Print<T>(IEnumerable<T> items) 
{ 
    var props = typeof(T).GetProperties(); 

    foreach (var prop in props) 
    { 
     Console.Write("{0}\t", prop.Name); 
    } 
    Console.WriteLine(); 

    foreach (var item in items) 
    { 
     foreach (var prop in props) 
     { 
      Console.Write("{0}\t", prop.GetValue(item, null)); 
     } 
     Console.WriteLine(); 
    } 
} 

यह बस प्रत्येक आइटम से अधिक प्रिंट, वर्ग के प्रत्येक संपत्ति पर लूप गुण का नाम मुद्रित करने के लिए तो और प्रत्येक आइटम के लिए यह के मूल्यों प्रिंट गुण।

मैं तर्क दूंगा कि आपको यहां जेनिक्स का उपयोग करना चाहिए (अन्य उत्तरों में सुझावों के विपरीत); आप संग्रह में वस्तुओं को एक प्रकार का होना चाहते हैं ताकि आप टेबल हेडर प्रिंट कर सकें।

तालिका स्वरूपण के लिए आप this question के उत्तरों की जांच कर सकते हैं।

+0

का उपयोग करने का कोई कारण नहीं है जो मैं खोज रहा था।बहुत धन्यवाद :) –

+0

यह मैं जो खोज रहा हूं उसके लिए काम करता है, जो एक बार 'ऑब्जेक्ट' के प्रॉपर्टी नेम (ओं) को प्रिंट करना है, और फिर सूची में प्रत्येक आइटम के लिए मूल्य प्रिंट करना है। धन्यवाद! – Shiva

7

ऑब्जेक्ट की ToString() विधि को उन सभी जानकारी को शामिल करने के लिए ओवरराइड करें जिन्हें आप प्रदर्शित करना चाहते हैं, और फिर जब भी आप चाहें इसे कॉल करें। अभिव्यक्तियों या जेनेरिकों की कोई ज़रूरत नहीं है।

+1

+1। यदि कक्षाएं सील कर दी जाती हैं, तो "विज़िटर पैटर्न" (वर्बोज़ उलटा पैटर्न मिलान ;-) का उपयोग किया जा सकता है। –

+0

और .NET विज़िटर पैटर्न में एक्सटेंशन विधियों के अलावा कुछ भी नहीं है। – Pradeep

+0

उपरोक्त समाधान वास्तव में अच्छा है। लेकिन, मेरे पास एक और मुद्दा है। कहें, उदाहरण के लिए, यदि मैं एक अनजान संग्रह पास करता हूं जैसे 'var result = पी। आईडी = o.PersonID पर आदेश में ओ से जुड़ने वाले व्यक्तियों से पी का चयन करें नया {p.Name, o.Name}; ' ' प्रिंट करें (नतीजा); 'इस मामले में, मैं इसे कैसे प्राप्त कर सकता हूं? –

3

यदि आपको नहीं पता कि किस प्रकार - यानी यह किसी भी प्रकार का हो सकता है - तो सबसे अच्छा विकल्प प्रतिबिंब का उपयोग करना है। यह एक अच्छा समाधान है। आपको ऐसा क्यों लगता है कि यह एक अच्छा समाधान नहीं है?

1

यह उदाहरण के लिए प्रदर्शन का उपयोग कर भाव आप के लिए एक प्रिंट विधि कैश:

class MyObject 
    { 
     public int Property1 { get; set;} 
     public string Property2 { get; set; } 
    } 
    class MyOtherObject 
    { 
     public int Property3 { get; set; } 
     public string Property4 { get; set; } 
    } 
    static void Main(string[] args) 
    { 
     Array.ForEach(new[] 
     { 
      new MyObject { Property1 = 1, Property2 = "P" }, 
      new MyObject { Property1 = 2, Property2 = "Q" } 
     }, Print); 
     Array.ForEach(new[] 
     { 
      new MyOtherObject { Property3 = 3, Property4 = "R" }, 
      new MyOtherObject { Property3 = 4, Property4 = "S" } 
     }, Print); 
     Console.ReadKey(); 
    } 
    static void Print<T>(T item) 
    { 
     ObjectPrinter<T>.PrintAction(item, Console.Out); 
    } 
    static class ObjectPrinter<T> 
    { 
     public static readonly Action<T, TextWriter> PrintAction = CreatePrintAction(); 
     private static Action<T, TextWriter> CreatePrintAction() 
     { 
      ParameterExpression item = Expression.Parameter(typeof(T), "item"); 
      ParameterExpression writer = Expression.Parameter(typeof(TextWriter), "writer"); 
      var writeLineMethod = typeof(TextWriter).GetMethod("WriteLine", BindingFlags.Public | BindingFlags.Instance, null, new[] { typeof(string) }, null); 
      var concatMethod = typeof(string).GetMethod("Concat", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(object), typeof(object) }, null); 
      var writeDashedLine = Expression.Call(
       writer, 
       writeLineMethod, 
       Expression.Constant(
        new String('-', 50) 
       ) 
      ); 
      var lambda = Expression.Lambda<Action<T, TextWriter>>(
       Expression.Block(
        writeDashedLine, 
        Expression.Block(
         from property in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance) 
         where property.GetGetMethod().GetParameters().Length == 0 
         select Expression.Call(
          writer, 
          writeLineMethod, 
          Expression.Call(
           null, 
           concatMethod, 
           Expression.Constant(
            property.Name + ":" 
           ), 
           Expression.Convert(
            Expression.Property(
             item, 
             property 
            ), 
            typeof(object) 
           ) 
          ) 
         ) 
        ), 
        writeDashedLine 
       ), 
       item, 
       writer 
      ); 
      return lambda.Compile(); 
     } 
    } 
संबंधित मुद्दे

 संबंधित मुद्दे