2011-11-03 13 views
6

Wystąpił dzisiaj nieoczekiwany problem, próbując przekształcić/deserializować DataContract zawierający bool [,] DataMember. Ani csc, ani środowisko wykonawcze nie wyraziły sprzeciwu wobec tej definicji, jednak wartości w deserializowanym boolu [,] DataMember właśnie nie były poprawne. Po przeczytaniu this thread, moją pierwszą reakcją było przekształcenie problematycznej właściwości w poszarpaną tablicę. Musiałem zrezygnować z tego podejścia wkrótce, ponieważ this article informuje, że postrzępione tablice wykonują marnie, gdy są dostępne po przekątnej lub losowo (dokładnie mój przypadek użycia). Więc skończyłem pisać napisaną wersję rozwiązania zaproponowanego w powyższym wątku msdn (konwertuj prostokątny na postrzępiony i visa versa przy eksporcie/imporcie, zobacz fragmenty kodu poniżej) i to działa dobrze.DataContractSerializer nie obsługuje prostokątnych tablic

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; 
} 

Zastanawiam się jednak, czy istnieje bardziej zwięzłe rozwiązanie tego lub innego podejścia.

+2

"że poszarpane tablice wykonują żałośnie" - ale czy to naprawdę ma znaczenie w porównaniu z we/wy, konwersją i serializacją? –

+1

Format utrwalania i format środowiska wykonawczego nie muszą być takie same. –

+1

W rdzeniu aplikacji omawiana macierz jest dostępna miliony razy (i jest to aplikacja telefoniczna, w której procesory nie są tak wydajne). Serializacja ma miejsce tylko po wyłączeniu lub zamknięciu aplikacji (rzadko). – javvin

Odpowiedz

0

Zamiast implementować GetDeserializedObject & GetObjectToSerialize, udostępniłbym inny obiekt do serializacji. Pojedynczo wymiarowa tablica wystarczyłaby przy okazji. Chciałbym to zrobić:

//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

Czy istnieje powód dlaczego trzeba wielowymiarową tablicę w pierwszej kolejności?

Jeśli używasz pojedynczą tablicę wymiaru, po prostu trzeba obliczyć właściwą indeksu, z bardzo prostego obliczenia:

array[x, y] 

staje

array[(y * width) + x] 

EDIT: jak wymieniono w komentarze, wtedy stracisz kilka przydatnych sprawdzeń granicznych. Jeśli to problem, można ponownie dodać je:

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

Uwaga: Y przypadki byłyby już rzucony przez tablicę, jeśli x jest prawidłowy.

+0

To prawda, ale tracisz pewne elementy sprawdzania ograniczeń (dla tablicy '3x4', możesz określić indeks z' (6,1) ', a to wciąż będzie obliczało pozycję w całej tablicy) –

+0

Masz rację , kontrole te należy wykonać ręcznie. Aktualizacja. – jv42

Powiązane problemy