2011-11-03 11 views
6

का समर्थन नहीं कर रहा है, आज मैं एक अप्रत्याशित समस्या में भाग गया, जिसमें एक बूल [,] डेटामेम्बर युक्त डेटाकंट्रैक को क्रमबद्ध/deserialize करने का प्रयास किया गया। न तो सीएससी और न ही रनटाइम ने इस परिभाषा पर आक्षेप किया, हालांकि deserialized बूल में मूल्य [,] डेटामेम्बर बस सही नहीं थे। this thread पढ़ने के बाद, मेरी प्रारंभिक प्रतिक्रिया समस्याग्रस्त संपत्ति को एक जंजीर सरणी में परिवर्तित करना था। मुझे जल्द ही उस दृष्टिकोण को त्यागना पड़ा, हालांकि this article से पता चलता है कि विकृत या यादृच्छिक रूप से (बिल्कुल मेरा उपयोग केस) पहुंचने पर जंजीर सरणी खराब तरीके से प्रदर्शन करती हैं। तो मैंने उपर्युक्त एमएसडीएन थ्रेड में प्रस्तावित समाधान के एक क्यूरेटेड संस्करण को लिखना समाप्त कर दिया (आयताकार से जुड़ा हुआ और निर्यात/आयात पर वीजा बनाम, नीचे कोड अंश देखें) और यह ठीक काम करता है।डेटाकंट्रैक्टसाइराइज़र आयताकार Arrays

public object GetDeserializedObject(object obj, Type targetType) 
{ 
    if (obj is GridArrayWrapper) 
    { 
     bool[,] arr; 
     GridArrayWrapper wrapper = (GridArrayWrapper)obj; 
     if (wrapper.Array == null) return null; 
     int d0 = wrapper.Array.Length; 
     if (d0 == 0) 
     { 
      return new bool[0, 0]; 
     } 
     var d1 = wrapper.Array[0].Length; 
     arr = new bool[d0, d1]; 
     for (int i = 0; i < d0; i++) 
     { 
      if (wrapper.Array[i].Length != d1) throw new ArgumentException("Not a rectangular array"); 
      for (var j = 0; j < d1; j++) 
      { 
       arr[i, j] = wrapper.Array[i][j]; 
      } 
     } 
     return arr; 
    } 
    return obj; 
} 

public object GetObjectToSerialize(object obj, Type targetType) 
{ 
    if (obj is bool[,]) 
    { 
     bool[,] arr = (bool[,])obj; 
     GridArrayWrapper wrapper = new GridArrayWrapper(); 
     int d0 = arr.GetLength(0); 
     int d1 = arr.GetLength(1); 
     wrapper.Array = new bool[d0][]; 
     for (int i = 0; i < wrapper.Array.Length; i++) 
     { 
      wrapper.Array[i] = new bool[d1]; 
      for (int j = 0; j < d1; j++) 
      { 
       wrapper.Array[i][j] = arr[i, j]; 
      } 
     } 
     return wrapper; 
    } 
    return obj; 
} 

मुझे आश्चर्य है कि अगर इस या किसी अन्य दृष्टिकोण के लिए अधिक संक्षिप्त समाधान है।

+2

"वह जंजीर सरणी खराब तरीके से प्रदर्शन करती हैं" - लेकिन क्या वास्तव में आई/ओ, रूपांतरण और क्रमबद्धता की तुलना में यह महत्वपूर्ण है? –

+1

दृढ़ता प्रारूप और रनटाइम प्रारूप समान नहीं होना चाहिए –

+1

एप्लिकेशन के मूल में प्रश्न में सरणी लाखों बार एक्सेस की जाती है (और यह एक फ़ोन ऐप है जहां सीपीयू शक्तिशाली नहीं हैं)। सीरियलाइजेशन केवल ऐप निष्क्रिय या बंद (कम) पर होता है। – javvin

उत्तर

0

GetDeserializedObject & GetObjectToSerialize को लागू करने के बजाय, मैं serialization के लिए एक अलग वस्तु का पर्दाफाश करता हूं। एक आयामी सरणी रास्ते से पर्याप्त होगा। एक कारण

//No Datamember here 
public bool[,] Data; 

[DataMember(Name="Data")] 
public bool[] XmlData 
{ 
    get { 
    bool[] tmp = new bool[Data.GetLength(0) * Data.GetLength(1)]; 
    Buffer.BlockCopy(Data, 0, tmp, 0, tmp.Length * sizeof(bool)); 
    return tmp; 
    } 
    set { 
    bool[,] tmp = new bool[,]; 
    Buffer.BlockCopy(value, 0, tmp, 0, value.Length * sizeof(bool)); 
    this.Data = tmp; 
    } 
} 
0

वहाँ कारण है कि आप पहली जगह में एक बहुआयामी सरणी की जरूरत है: मैं इस करना होगा?

आप एक भी आयाम सरणी का उपयोग करते हैं, तो आप सिर्फ उचित सूचकांक की गणना करने, एक बहुत ही सरल गणना के साथ है:

array[x, y] 

हो जाता है

array[(y * width) + x] 

संपादित करें: के रूप में में mentionned टिप्पणियां, फिर आप कुछ उपयोगी सीमाओं की जांच खो देंगे। यदि यह एक मुद्दा है, तो आप उन्हें फिर से जोड़ सकते हैं:

if (x < 0 || x > width || y < 0 || y > height) 
    throw new IndexOutOfRangeException(); 

नोट: y मामलों को पहले से ही सरणी द्वारा फेंका होगा अगर एक्स मान्य है।

+0

सच है, लेकिन आप सीमाओं की जांच के कुछ तत्व खो देते हैं ('3x4' सरणी के लिए, आप' (6,1) 'की अनुक्रमणिका निर्दिष्ट कर सकते हैं, और यह अभी भी समग्र सरणी के भीतर एक स्थिति की गणना करेगा) –

+0

आप सही हैं , इन चेकों को हाथ से किया जाना चाहिए। अद्यतन कर रहा है। – jv42

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