XMLにシリアル化し、シリアル化されたオブジェクトのタイプを含めます
-
05-07-2019 - |
質問
C#での XmlDocument
へのオブジェクトのシリアル化に関する以前の質問、いくつかの障害情報をasmxスタイルのWebサービス呼び出しから返された XmlDocument
にシリアル化する必要がありました。クライアントでは、 XmlDocument
をオブジェクトに逆シリアル化する必要があります。
型を知っていればこれは簡単ですが、逆シリアル化する型も XmlDocument
でエンコードされる柔軟なアプローチが必要だと思いました。現在、次のように計算されたタイプ名を持つ XmlDocument
に XmlNode
を追加することで、手動で実行しています。
Type type = fault.GetType();
string assemblyName = type.Assembly.FullName;
// Strip off the version and culture info
assemblyName = assemblyName.Substring(0, assemblyName.IndexOf(",")).Trim();
string typeName = type.FullName + ", " + assemblyName;
クライアントでは、まずこの型名を XmlDocument
から取得し、 XmlSerialiser
に渡す型オブジェクトを作成します。
object fault;
XmlNode faultNode = e.Detail.FirstChild;
XmlNode faultTypeNode = faultNode.NextSibling;
// The typename of the fault type is the inner xml of the first node
string typeName = faultTypeNode.InnerXml;
Type faultType = Type.GetType(typeName);
// The serialised data for the fault is the second node
using (var stream = new StringReader(faultNode.OuterXml))
{
var serialiser = new XmlSerializer(faultType);
objectThatWasSerialised = serialiser.Deserialize(stream);
}
return (CastToType)fault;
これは総当たり的なアプローチであり、どこかに手動で記録するのではなく、シリアル化された型の型名を何らかの形で含むよりエレガントなソリューションがあるのではないかと思っていましたか?
解決
同様の問題に直面していましたが、同じ解決策を思いつきました。私の知る限り、それがXMLシリアル化で型を値と一緒に保つ唯一の方法です。
あなたも私と同じようにアセンブリバージョンを切り取っているようです。ただし、ジェネリック型のシグネチャは次のように見えるため、ジェネリック型で問題が発生することに言及したいと思います。
System.Nullable`1[[System.Int, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
だから、バージョン管理の問題を取り除くのに十分であると思われるアセンブリバージョンのみをカットする関数を作成しました:
private static string CutOutVersionNumbers(string fullTypeName)
{
string shortTypeName = fullTypeName;
var versionIndex = shortTypeName.IndexOf("Version");
while (versionIndex != -1)
{
int commaIndex = shortTypeName.IndexOf(",", versionIndex);
shortTypeName = shortTypeName.Remove(versionIndex, commaIndex - versionIndex + 1);
versionIndex = shortTypeName.IndexOf("Version");
}
return shortTypeName;
}
他のヒント
Neil、クライアントとサーバーの両方で同じタイプにする必要があるのはなぜですか?
クライアントでまだASMXを使用していますか? ASMXは障害を適切にサポートしていないため、これが理由となります。
また、単純な switch ステートメントでは使用する正しいタイプを決定できないほど多くの異なる障害タイプがありますか?