今日、予期せぬ問題が発生し、bool [、] DataMemberを含むDataContractをシリアル化/逆シリアル化しようとしました。 cscもランタイムもこの定義に反対しませんでしたが、逆シリアル化されたbool [、] DataMemberの値は正しくありませんでした。 this threadを読んだ後、私の最初の反応は問題のあるプロパティをギザギザの配列に変換することでした。私はすぐにそのアプローチを放棄しなければならなかったが、this articleは斜めにまたはランダムにアクセスしたときにギザギザの配列が悲惨に実行されることを知らせている。だから、上記のmsdnスレッドで提案されているソリューションのキュレーション版を作成してしまいました(エクスポート/インポート時にギザギザとビザの逆の変換、下のコードの抜粋を参照)。長方形配列をサポートしていないDataContractSerializer
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;
}
私は、この方法または別の方法についてより簡潔な解決策があると思っています。
"ギザギザの配列は悲惨に実行されます" - しかし、I/O、変換、シリアライゼーションに比べて本当に重要ですか? –
パーシスタンスフォーマットとランタイムフォーマットは同じである必要はありません –
アプリケーションのコアでは、問題のアレイは何百万回もアクセスされます(そして、CPUがそれほど強力でない電話アプリです)。シリアライゼーションは、アプリケーションの非アクティブ化またはクローズ時(まれに)にのみ発生します。 – javvin