ものがたり(旧)

atsushieno.hatenablog.com に続く

XsdDataContractImporterについて(半分くらい)

最近ここに技術系の話を書いていなかったので、ひさしぶりにWCFの話でも書いてみようかと思う。

XsdDataContractImporterは、svcutil.exeで使われているWCFのクラスライブラリの一部で、XML Schemaからdata contract typesを生成するものだ。XmlSchemaSetからCodeCompileUnitを生成するもの、と言えば、より具体的だろうか。

System.Xml.Serializationにも、XML SchemaからCodeDomを生成するXmlSchemaImporterというものが存在していて、目的はだいたい同じなんだけど、シリアライゼーションの仕組みはdata contractとXmlSerializerではだいぶ違っているし、そのため、これらが生成するクラスの構造もだいぶ違う。XsdDataContractImporterは、xml serializationとは全く異なる実装をゼロから作っているはずだ。具体的には:

  • XmlSchemaImporterが生成するのは、ひとつのCodeNamespaceを前提とした型の集合だ。

一方、XsdDataContractImporterでは、スキーマ名前空間ごとにCodeNamespaceを生成する。XmlSchemaImporterは異なる名前空間で同一のlocal nameをもつelementを取り込むことに失敗している。

  • スキーマから既知の)派生型は全てKnownTypeAttributeとして基底型に追加される
  • complexTypeについて、
    • 属性は一切サポートされない。RefやIdなど、data contractが必要とする属性のみ処理される
    • simple content extensionはサポートされない
    • simple content restrictionは、simple contentをもつcomplexTypeを親とすることになり、最終的にsimple content extensionが上記の通りになるので、やはりサポートされない
    • complex content restrictionはサポートされない(基底型と派生型でメンバが重複しうるので、サポートが煩雑になる)
    • トップレベルのparticleでは、sequence以外はサポートされない
    • そのsequenceの中では、elementのみが出現できる(groupRef, choice, any, sequenceは出現できない)
    • sequenceの中に出現するelementは、同じ名前をもってはならない
    • 上記の要件を満たす型はclassとなり、そのsequenceに含まれるelementがそのclassのメンバーになる
  • simpleTypeはenumとしてサポートされるが、さまざまな条件がある:
    • enumeration facetをもつstringからのsimple type restrictionは、通常のenumとなり、enumeration valueがそのメンバーになる(他の型からの派生はサポートされない)
    • listは、基底型は子要素として記述した上記のようなsimple type restrictionであれば、FlagsAttributeをつけられたenumとなる(その他の場合はサポートされない)

簡単に言えば、これらの制約は要するに、DataContractExporterで生成したスキーマくらいしかサポートしませんよ、ということだと思う。data contractにおけるスキーマの対応守備範囲はxml serializationよりも狭い。data contractでは対応範囲が狭くて困るという場合は、XsdDataContractImporterのOptions (of ImportOptions type)にImportXmlType = true を設定すると、守備範囲外のものはXmlNodeの配列として読み書きできるようになる(ニッチなのでmonoではまだ実装していないけど)。

これらはあくまで制約の話で、elementにmaxOccurs="unbounded"がついたら配列になる等、いくつかのバリエーションがある。具体的なスキーマをもとにこの辺を説明(?)したものをsvn放り込んでみたので、詳しく知りたい人は見てみるといいと思う。でもそんなこと知って何になるの…

ちなみに表題に「半分くらい」って書いてあるのは、ImportXmlTypeなど各種オプションを設定した場合に出力されるコードについて何も書いていないからで、残り半分について書く予定は今のところ無い。