2009-07-09 15 views
10

का उपयोग कर ऑब्जेक्ट मैपिंग के लिए IDataReader जेनिक्स का उपयोग करके मैं क्लास ऑब्जेक्ट में DataReader ऑब्जेक्ट को कैसे मैप कर सकता हूं?सी # - जेनेरिक

public class Mapper<T> 
    { 
     public static List<T> MapObject(IDataReader dr) 
     { 
      List<T> objects = new List<T>(); 

      while (dr.Read()) 
      { 
       //Mapping goes here... 
      } 

      return objects; 
     } 
    } 

और बाद में मैं जैसे निम्नलिखित इस वर्ग-विधि कॉल करने की जरूरत है:: - वर्ग होना चाहिए

IDataReder dataReader = DBUtil.Fetchdata("SELECT * FROM Book"); 

List<Book> bookList = Mapper<Book>.MapObject(dataReder); 

foreach (Book b in bookList) 
{ 
    Console.WriteLine(b.ID + ", " + b.BookName); 
} 

ध्यान दें कि, मैपर

उदाहरण के लिए मैं निम्नलिखित कार्य करने होंगे टी

+0

एक सुझाव - उपज रिटर्न के साथ एक आईनेमेरेबल में पढ़ें। –

+0

// मैपिंग यहां जाता है, ठीक है मैंने आपको अपने उत्तर में दिखाया है, आप किसी भी ऑब्जेक्ट को डेटा रीडर पर मैप कर सकते हैं (अधिक सटीक: किसी आईडीटाइडर से किसी ऑब्जेक्ट में मान इंजेक्शन करना) – Omu

+0

आप एक का उपयोग क्यों नहीं करेंगे तब समर्पित ओआरएम? डैपर जैसे माइक्रो-ओआरएम यहां एक अच्छा फिट प्रतीत होता है। – nawfal

उत्तर

3

मैं इस

मैं इस तरह कर रहा हूँ के लिए ValueInjecter का उपयोग करें:

while (dr.Read()) 
    { 
     var o = new User(); 
     o.InjectFrom<DataReaderInjection>(dr); 
     yield return o; 
    } 

तुम इस के लिए इस ValueInjection जरूरत है काम करने के लिए:

public class DataReaderInjection : KnownSourceValueInjection<IDataReader> 
    { 
     protected override void Inject(IDataReader source, object target, PropertyDescriptorCollection targetProps) 
     { 
      for (var i = 0; i < source.FieldCount; i++) 
      { 
       var activeTarget = targetProps.GetByName(source.GetName(i), true); 
       if (activeTarget == null) continue; 

       var value = source.GetValue(i); 
       if (value == DBNull.Value) continue; 

       activeTarget.SetValue(target, value); 
      } 
     } 
    } 
+0

कहीं आम और उपयोगी इंजेक्शन की कोई पुस्तकालय है? –

+0

@PavelHodek लाइब्रेरी नहीं है लेकिन वैलेंटाइंसर के मुख्य डेमो समाधान में और कोडप्लेक्स पृष्ठों में भी – Omu

+0

कुछ चीजें हैं। 1) आप मूल्य निर्धारित करने के लिए प्रतिबिंब का उपयोग कर रहे हैं, यह प्रदर्शन के लिए बुरा है। अभिव्यक्ति मार्ग जाओ। 2) आपकी लाइब्रेरी में DataReaderInjection और KnownSourceValueInjection कहां है? मुझे लगता है कि आपने इस जवाब के बाद नाम बदल दिए हैं? 3) क्या यह पाठक के दौरान हर बार दृश्यों के पीछे प्रतिबिंब का उपयोग कर रहा है। संपत्ति नाम पाने के लिए लूप पढ़ें? मुझे उम्मीद है कि नहीं, लेकिन KnownSourceValueInjection क्लास को देखे बिना खुद को मनाने के लिए प्रतिबद्ध नहीं है। – nawfal

2

अच्छी तरह से, मुझे नहीं पता कि यह यहां फिट बैठता है, लेकिन आप उपज कीवर्ड

का उपयोग कर सकते हैं
public static IEnumerable<T> MapObject(IDataReader dr, Func<IDataReader, T> convertFunction) 
     { 
      while (dr.Read()) 
      { 
       yield return convertFunction(dr); 
      } 
     } 
+0

+1 DI का दिलचस्प उपयोग। यह अच्छा होगा कि टी प्रकार कन्वर्टफंक्शन के कार्यान्वयन को भी प्रदान करे। : डी –

+0

यह अच्छा डीआई है और इसे ओमू के समाधान के साथ जोड़ा जा सकता है। –

1

यह बहुत कारण यह है कि आप मूल रूप से दो अज्ञात एक साथ मैप करना चाहते हैं के लिए करना बहुत मुश्किल होने जा रहा है। आपके सामान्य ऑब्जेक्ट में प्रकार अज्ञात है, और आपके डेटारेडर में तालिका अज्ञात है।

तो मैं क्या सुझाव दूंगा कि आप किसी इकाई की गुणों को संलग्न करने के लिए कुछ प्रकार की कॉलम विशेषता बनाते हैं। और फिर उन संपत्ति विशेषताओं को देखें और डेटारेडर में उन विशेषताओं से डेटा देखने का प्रयास करें।

आपकी सबसे बड़ी समस्या होने जा रही है, क्या होता है यदि पाठकों में से कोई गुण पाठक में नहीं मिलता है, या इसके विपरीत, पाठक में से एक स्तंभ इकाई में नहीं मिलता है।

शुभकामनाएं, लेकिन यदि आप ऐसा कुछ करना चाहते हैं, तो आप शायद ओआरएम या कम से कम किसी प्रकार के सक्रिय रिकॉर्ड कार्यान्वयन चाहते हैं।

+0

मेरे उत्तर को देखो, यह कठिन नहीं है :), और – Omu

1

ऑफहैंड के बारे में सोचने का सबसे आसान तरीका प्रत्येक कॉलम को परिवर्तित करने और अपनी पुस्तक बनाने के लिए Func<T,T> प्रतिनिधि को आपूर्ति करना होगा।

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

1

मुझे नहीं लगता कि आप किसी रूप में फ़ील्ड के बीच संबंधों को परिभाषित करने में सक्षम होंगे। इस आलेख पर नज़र डालें और मैपिंग को परिभाषित करने के तरीके पर विशेष ध्यान दें, यह आपके लिए काम कर सकता है।

http://www.c-sharpcorner.com/UploadFile/rmcochran/elegant_dal05212006130957PM/elegant_dal.aspx

1

किस बारे में निम्नलिखित अगर यह वाक्य रचना सही है

abstract class DataMapper 
{ 
    abstract public object Map(IDataReader); 
} 

class BookMapper : DataMapper 
{ 
    override public object Map(IDataReader reader) 
    { 
     ///some mapping stuff 
     return book; 
    } 
} 

public class Mapper<T> 
{ 
    public static List<T> MapObject(IDataReader dr) 
    { 
     List<T> objects = new List<T>(); 
     DataMapper myMapper = getMapperFor(T); 
     while (dr.Read()) 
     { 
      objects.Add((T)myMapper(dr)); 
     } 

     return objects; 
    } 

    private DataMapper getMapperFor(T myType) 
    { 
     //switch case or if or whatever 
     ... 
     if(T is Book) return bookMapper; 

    } 
} 

पता नहीं है, लेकिन मुझे आशा है कि यू विचार मिलता है।

+0

की कोई विशेषता नहीं है, यदि आप अन्य स्थितियों से बच सकते हैं और बहुरूपता पर भरोसा कर सकते हैं बशर्ते पुस्तक वर्ग स्वयं कुछ Func लागू करता है। – nawfal

1

पर एक नज़र मैं सुझाव है कि आप इस के लिए AutoMapper का उपयोग करना चाहते हैं।

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