---
lang: ja-jp
breaks: true
---
# MessagePack で `DataSet` `DataTable` を シリアライズ/デシリアライズ したい C# 2021-11-13
`DataSet`、`DataTable` 標準のシリアライザを使用する為、シリアライズ後のサイズは大きくなるがとりあえず対応出来た。
## DataTable
### NativeDataTableFormatter
```csharp=
using System;
using System.Buffers;
using System.Data;
using System.IO;
namespace MessagePack.Formatters
{
/// <summary>
/// Serialize by .NET native DataTable XML format.
/// </summary>
public sealed class NativeDataTableFormatter : IMessagePackFormatter<DataTable>
{
public static readonly NativeDataTableFormatter Instance = new NativeDataTableFormatter();
public void Serialize(
ref MessagePackWriter writer,
DataTable value,
MessagePackSerializerOptions options
)
{
if (value == null)
{
writer.WriteNil();
}
else
{
try
{
using (var stream = new MemoryStream())
{
value.WriteXml(
stream,
XmlWriteMode.WriteSchema
);
byte[] date_Data = null;
date_Data = stream.ToArray();
stream.Close();
writer.Write(date_Data);
}
}
catch (Exception ex)
{
throw;
}
}
}
public DataTable Deserialize(
ref MessagePackReader reader,
MessagePackSerializerOptions options
)
{
if (reader.TryReadNil())
{
return default(DataTable);
}
else
{
DataTable dateData = new DataTable();
try
{
byte[] buffer = reader.ReadBytes().Value.ToArray();
using (var stream = new MemoryStream(buffer))
{
XmlReadMode xmlReadMode = dateData.ReadXml(stream);
stream.Close();
}
}
catch (Exception ex)
{
throw;
}
return dateData;
}
}
}
public sealed class NativeDataTableArrayFormatter : IMessagePackFormatter<DataTable[]>
{
public static readonly NativeDataTableArrayFormatter Instance = new NativeDataTableArrayFormatter();
public void Serialize(ref MessagePackWriter writer, DataTable[] value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
writer.WriteArrayHeader(value.Length);
for (int i = 0; i < value.Length; i++)
{
NativeDataTableFormatter.Instance.Serialize(ref writer, value[i], options);
}
}
}
public DataTable[] Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
var len = reader.ReadArrayHeader();
if (len == 0)
{
return Array.Empty<DataTable>();
}
var array = new DataTable[len];
for (int i = 0; i < array.Length; i++)
{
DataTable dataTable = NativeDataTableFormatter.Instance.Deserialize(ref reader, options);
array[i] = dataTable;
}
return array;
}
}
}
```
### NativeDataTableResolver
```csharp=
using System;
using System.Data;
using MessagePack.Formatters;
using MessagePack.Internal;
namespace MessagePack.Resolvers
{
public sealed class NativeDataTableResolver : IFormatterResolver
{
/// <summary>
/// The singleton instance that can be used.
/// </summary>
public static readonly NativeDataTableResolver Instance;
/// <summary>
/// A <see cref="MessagePackSerializerOptions"/> instance with this formatter pre-configured.
/// </summary>
public static readonly MessagePackSerializerOptions Options;
static NativeDataTableResolver()
{
Instance = new NativeDataTableResolver();
Options = MessagePackSerializerOptions.Standard.WithResolver(Instance);
}
private NativeDataTableResolver()
{
}
public IMessagePackFormatter<T> GetFormatter<T>()
{
return FormatterCache<T>.Formatter;
}
private static class FormatterCache<T>
{
public static readonly IMessagePackFormatter<T> Formatter;
static FormatterCache()
{
Formatter = (IMessagePackFormatter<T>)NativeDataTableResolverGetFormatterHelper
.GetFormatter(typeof(T));
}
}
}
}
namespace MessagePack.Internal
{
internal static class NativeDataTableResolverGetFormatterHelper
{
internal static object GetFormatter(Type t)
{
if (t == typeof(DataTable))
{
return NativeDataTableFormatter.Instance;
}
else if (t == typeof(DataTable[]))
{
return NativeDataTableArrayFormatter.Instance;
}
return null;
}
}
}
```
## DataSet
### NativeDataSetFormatter
```csharp=
using System;
using System.Buffers;
using System.Data;
using System.IO;
namespace MessagePack.Formatters
{
/// <summary>
/// Serialize by .NET native DataSet XML format.
/// </summary>
public sealed class NativeDataSetFormatter : IMessagePackFormatter<DataSet>
{
public static readonly NativeDataSetFormatter Instance = new NativeDataSetFormatter();
public void Serialize(
ref MessagePackWriter writer,
DataSet value,
MessagePackSerializerOptions options
)
{
if (value == null)
{
writer.WriteNil();
}
else
{
try
{
using (var stream = new MemoryStream())
{
value.WriteXml(
stream,
XmlWriteMode.WriteSchema
);
byte[] date_Data = null;
date_Data = stream.ToArray();
stream.Close();
writer.Write(date_Data);
}
}
catch (Exception ex)
{
throw;
}
}
}
public DataSet Deserialize(
ref MessagePackReader reader,
MessagePackSerializerOptions options
)
{
if (reader.TryReadNil())
{
return default(DataSet);
}
else
{
DataSet dateData = new DataSet();
try
{
byte[] buffer = reader.ReadBytes().Value.ToArray();
using (var stream = new MemoryStream(buffer))
{
XmlReadMode xmlReadMode = dateData.ReadXml(stream);
stream.Close();
}
}
catch (Exception ex)
{
throw;
}
return dateData;
}
}
}
public sealed class NativeDataSetArrayFormatter : IMessagePackFormatter<DataSet[]>
{
public static readonly NativeDataSetArrayFormatter Instance = new NativeDataSetArrayFormatter();
public void Serialize(ref MessagePackWriter writer, DataSet[] value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
writer.WriteArrayHeader(value.Length);
for (int i = 0; i < value.Length; i++)
{
NativeDataSetFormatter.Instance.Serialize(ref writer, value[i], options);
}
}
}
public DataSet[] Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
var len = reader.ReadArrayHeader();
if (len == 0)
{
return Array.Empty<DataSet>();
}
var array = new DataSet[len];
for (int i = 0; i < array.Length; i++)
{
DataSet DataSet = NativeDataSetFormatter.Instance.Deserialize(ref reader, options);
array[i] = DataSet;
}
return array;
}
}
}
```
### NativeDataSetResolver
```csharp=
using System;
using System.Data;
using MessagePack.Formatters;
using MessagePack.Internal;
namespace MessagePack.Resolvers
{
public sealed class NativeDataSetResolver : IFormatterResolver
{
/// <summary>
/// The singleton instance that can be used.
/// </summary>
public static readonly NativeDataSetResolver Instance;
/// <summary>
/// A <see cref="MessagePackSerializerOptions"/> instance with this formatter pre-configured.
/// </summary>
public static readonly MessagePackSerializerOptions Options;
static NativeDataSetResolver()
{
Instance = new NativeDataSetResolver();
Options = MessagePackSerializerOptions.Standard.WithResolver(Instance);
}
private NativeDataSetResolver()
{
}
public IMessagePackFormatter<T> GetFormatter<T>()
{
return FormatterCache<T>.Formatter;
}
private static class FormatterCache<T>
{
public static readonly IMessagePackFormatter<T> Formatter;
static FormatterCache()
{
Formatter = (IMessagePackFormatter<T>)NativeDataSetResolverGetFormatterHelper
.GetFormatter(typeof(T));
}
}
}
}
namespace MessagePack.Internal
{
internal static class NativeDataSetResolverGetFormatterHelper
{
internal static object GetFormatter(Type t)
{
if (t == typeof(DataSet))
{
return NativeDataSetFormatter.Instance;
}
else if (t == typeof(DataSet[]))
{
return NativeDataSetArrayFormatter.Instance;
}
return null;
}
}
}
```
## 型付DataSet
### TypedDataSetFormatter
```csharp=
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq.Expressions;
using System.Reflection;
namespace MessagePack.Formatters
{
/// <summary>
/// Serialize by .NET typed DataSet XML format.
/// </summary>
public sealed class TypedDataSetFormatter<TDataSet> : IMessagePackFormatter<TDataSet>
{
public static readonly TypedDataSetFormatter<TDataSet> Instance = new TypedDataSetFormatter<TDataSet>();
private static Dictionary<Guid, Func<TDataSet>> ConstructorInfoCache = new ();
public void Serialize(
ref MessagePackWriter writer,
TDataSet value,
MessagePackSerializerOptions options
)
{
if ( value == null
|| value.GetType().BaseType != typeof(DataSet)
)
{
writer.WriteNil();
}
else
{
try
{
using (var stream = new MemoryStream())
{
DataSet dataSet = value as DataSet;
dataSet.WriteXml(
stream,
XmlWriteMode.WriteSchema
);
byte[] date_Data = null;
date_Data = stream.ToArray();
stream.Close();
writer.Write(date_Data);
}
}
catch (Exception ex)
{
throw;
}
}
}
public TDataSet Deserialize(
ref MessagePackReader reader,
MessagePackSerializerOptions options
)
{
if (reader.TryReadNil())
{
return default(TDataSet);
}
else
{
Guid key = typeof(TDataSet).GUID;
Func<TDataSet> func = null;
lock (ConstructorInfoCache)
{
if (ConstructorInfoCache.TryGetValue(key, out func) == false)
{
ConstructorInfo constructorInfo = typeof(TDataSet).GetConstructor(Type.EmptyTypes);
ParameterExpression[] parameterExpressions = Array.Empty<ParameterExpression>();
NewExpression instance = Expression.New(
constructorInfo,
parameterExpressions
);
Expression<Func<TDataSet>> lambda = Expression.Lambda<Func<TDataSet>>(
instance,
parameterExpressions
);
func = lambda.Compile();
ConstructorInfoCache.Add(key, func);
}
}
DataSet dateData = func() as DataSet;
try
{
byte[] buffer = reader.ReadBytes().Value.ToArray();
using (var stream = new MemoryStream(buffer))
{
XmlReadMode xmlReadMode = dateData.ReadXml(stream);
stream.Close();
}
}
catch (Exception ex)
{
throw;
}
return (TDataSet)(object)dateData;
}
}
}
public sealed class TypedDataSetArrayFormatter<TDataSet> : IMessagePackFormatter<TDataSet[]>
{
public static readonly TypedDataSetArrayFormatter<TDataSet> Instance = new TypedDataSetArrayFormatter<TDataSet>();
public void Serialize(ref MessagePackWriter writer, TDataSet[] value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
writer.WriteArrayHeader(value.Length);
for (int i = 0; i < value.Length; i++)
{
TypedDataSetFormatter<TDataSet>.Instance.Serialize(ref writer, value[i], options);
}
}
}
public TDataSet[] Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
var len = reader.ReadArrayHeader();
if (len == 0)
{
return Array.Empty<TDataSet>();
}
var array = new TDataSet[len];
for (int i = 0; i < array.Length; i++)
{
TDataSet DataSet = TypedDataSetFormatter<TDataSet>.Instance.Deserialize(ref reader, options);
array[i] = DataSet;
}
return array;
}
}
}
```
### TypedDataSetResolver
```csharp=
using System;
using System.Data;
using MessagePack.Formatters;
using MessagePack.Internal;
namespace MessagePack.Resolvers
{
public sealed class TypedDataSetResolver : IFormatterResolver
{
/// <summary>
/// The singleton instance that can be used.
/// </summary>
public static readonly TypedDataSetResolver Instance;
/// <summary>
/// A <see cref="MessagePackSerializerOptions"/> instance with this formatter pre-configured.
/// </summary>
public static readonly MessagePackSerializerOptions Options;
static TypedDataSetResolver()
{
Instance = new TypedDataSetResolver();
Options = MessagePackSerializerOptions.Standard.WithResolver(Instance);
}
private TypedDataSetResolver()
{
}
public IMessagePackFormatter<T> GetFormatter<T>()
{
return FormatterCache<T>.Formatter;
}
private static class FormatterCache<T>
{
public static readonly IMessagePackFormatter<T> Formatter;
static FormatterCache()
{
Formatter = (IMessagePackFormatter<T>)TypedDataSetResolverGetFormatterHelper
.GetFormatter<T>();
}
}
}
}
namespace MessagePack.Internal
{
internal static class TypedDataSetResolverGetFormatterHelper
{
internal static object GetFormatter<TDataSet>()
{
Type t = typeof(TDataSet);
if (t.BaseType == typeof(DataSet))
{
return TypedDataSetFormatter<TDataSet>.Instance;
}
else if (t.BaseType == typeof(System.Array))
{
if (t.GetElementType()?.BaseType == typeof(DataSet))
{
return TypedDataSetArrayFormatter<TDataSet>.Instance;
}
}
return null;
}
}
}
```
## MessagePackSerializerOptions
```csharp=
public class MessagePackSerializerOption
{
public static MessagePackSerializerOptions Option;
static MessagePackSerializerOption()
{
IFormatterResolver customResolver = MessagePack.Resolvers.CompositeResolver.Create(
NativeDateTimeResolver.Instance,
TypedDataSetResolver.Instance,
NativeDataSetResolver.Instance,
NativeDataTableResolver.Instance,
ContractlessStandardResolverAllowPrivate.Instance
);
Option = ContractlessStandardResolverAllowPrivate.Options
.WithCompression(MessagePackCompression.Lz4Block)
.WithResolver(customResolver)
;
}
}
```
###### tags: `MessagePack` `DataSet` `DataTable` `型付DataSet` `シリアライズ` `デシリアライズ` `式木` `キャッシュ` `C#`