- PR -

.NET Remotingで、あるTimeSpan型の値がシリアライズ不可

1
投稿者投稿内容
ryuuji
ベテラン
会議室デビュー日: 2003/07/10
投稿数: 53
お住まい・勤務地: 東京都
投稿日時: 2005-06-29 22:34
質問という訳では無いのですが、詳細をご存知の方が居たらと思い投稿致します。

バグなのか仕様なのか分かりませんが.NET RemotingでRemotingサーバからDataSet型オブジェクトをクライアントへ渡す際、以下の条件で必ずFormatExceptionが投げられます。

DataTableにTimeSpan型の列があり、そのデータに0秒未満の値(e.g. 00:00:00.001)が含まれている。

例としてRemotingサーバが公開するクラスメソッドに以下のようなものがあるとします。

コード:

public DataSet GetDataSet(TimeSpan ts)
{
DataSet dataSet = new DataSet();
dataSet.Tables.Add().Columns.Add("TimeSpan", typeof(TimeSpan)); // 列追加
dataSet.Tables[0].Rows.Add(new object[] { ts }); // tsを追加するだけ
return dataSet; // これがクライアントへ渡る
}



このTimeSpan型tsが以下のように0秒未満の端数付きで作られると必ずFormatException例外になってしまいます。

コード:

public void Hoge()
{
RemotingServer server = this.GetRemotingServer(); // Remotingサーバを得る
server .GetDataSet(TimeSpan.Parse("00:00:00")); // これはOK
server .GetDataSet(TimeSpan.Parse("00:00:00.0")); // これはOK
server .GetDataSet(TimeSpan.Parse("00:00:00.1")); // これはNG
}



ちなみにスタックトレースはこんな感じです。

System.Reflection.TargetInvocationException: 呼び出しのターゲットが例外をスローしました。 ---> System.FormatException: 文字列は有効な TimeSpan 型の値として認識されませんでした。
at System.Xml.XmlConvert.ToTimeSpan(String s)
at System.Data.Common.TimeSpanStorage.ConvertXmlToObject(String s)
at System.Data.DataColumn.ConvertXmlToObject(String s)
at System.Data.XmlDataLoader.LoadData(DataRow& row, DataTable parentTable, Boolean[] foundColumns)
at System.Data.XmlDataLoader.LoadData(DataTable parentTable)
at System.Data.XmlDataLoader.LoadData(XmlReader reader)
at System.Data.DataSet.ReadXmlDiffgram(XmlReader reader)
at System.Data.DataSet.ReadXml(XmlReader reader, XmlReadMode mode, Boolean denyResolving)
at System.Data.DataSet.ReadXml(XmlReader reader, XmlReadMode mode)
at System.Data.DataSet..ctor(SerializationInfo info, StreamingContext context)


どうやらDataSet型オブジェクトのデシリアライズで例外が起きるようです。DataSetをシリアライズするとTimeSpan型の値は"00:00:00"が"PT0S"などの文字列に変換されるようなのですが(これはSoapDuration.Parse()でTimeSpan型へパースできます)、"00:00:00.1"などの端数値を持つTimeSpan型は"P"という文字列に変換され、この時デシリアライズに失敗するようです。

上記について情報をお持ちの方いましたら宜しくお願い致します。

[ メッセージ編集済み 編集者: ryuuji 編集日時 2005-06-29 22:35 ]
Atsushi.Eno
ベテラン
会議室デビュー日: 2003/04/23
投稿数: 60
投稿日時: 2005-06-30 02:50
.NET Framework(XmlConvert)のバグです。以下コレを読むための前提:

- DataSetのシリアライゼーションはruntimeでもxmlでもWriteXml(Serializable)相当の内容になります。
- PというのはXML Schema Datatypesのduration(ISO 8601の書式で表される文字列です)で使用されるPのようです。

時分秒(ミリ秒を除く)が全部0だと、ミリ秒まで見てくれないようです。XmlConvert.ToString (new TimeSpan (1, 0, 0, 0, 1))も"P1D"となってしまうようなので。

.NET 2.0 (beta2)では直っています。
# monoも小数点以下まで見てなかったので直しちゃいました
ryuuji
ベテラン
会議室デビュー日: 2003/07/10
投稿数: 53
お住まい・勤務地: 東京都
投稿日時: 2005-06-30 13:20
Atsushi.Enoさん、Web上にはあまり情報が無く、気になっていました。
とてもすっきりしました。ありがとうございました。

6/30 追記:
.NET Remotingでしか起こらないような書き方をしてしまいましたが、DataSet型オブジェクトがシリアライズ/デシリアライズされるようなケースで発生します。例えばDataSet型を返すようなWebMethodも該当します。

[ メッセージ編集済み 編集者: ryuuji 編集日時 2005-06-30 14:53 ]
1

スキルアップ/キャリアアップ(JOB@IT)