3

以下を検討してください。XmlSerializer でシリアル化したいクラスがあります。このクラスには、型が別のアセンブリにある型制約を持つパブリック ジェネリック メソッドがあります。

using BarStuff;

namespace FooStuff {
  public class Foo {
    ...
    public T GetBar<TBar, T>( string key ) where TBar : Bar<T> {
      ...
    }
  }
}

XmlSerializer 自体がメソッドに関係しているとは思わないでしょうし、通常は関係ありません。次の両方が正常に機能します。

//private, serializer doesn't care about it
private T GetBar<TBar, T>( string key ) where TBar : Bar<T> {
  ...
}

//no generic type constraint, serializer also doesn't care about it
public Bar GetBar( string key ) {
  ...
}   

また、型 Bar が Foo と同じアセンブリにある場合、シリアライザーも完全に満足します。

最初の例を実行すると、Bar が別のアセンブリで定義されている場合、プロジェクト参照にそのアセンブリが既にある場合でも、 Bar を含むアセンブリへの参照を追加する必要があることを示す実行時例外が発生します。XmlInclude を使用してこれを回避できます。

[XmlInclude(typeof(Bar))]
public class Foo {
  public T GetBar<TBar, T>( string key ) where TBar : Bar<T> {
    ...
  }
}

ただし、Bar がシリアライズ可能ではなく、そうすべき理由がない場合、インターフェイスをタイプとして返​​すパブリック プロパティなど、シリアライズできないものに最初にヒットしたときに実行時例外が発生します。パラメーターなしのコンストラクターなどのないクラス!

関連するが詳細ではない:ジェネリック型制約を使用すると、XmlSerializer が InvalidOperationException をスローします。

また、この問題に対する Microsoft の見解

4

1 に答える 1

3

いくつかの回避策:

  • DataContractSerializerなどの別のシリアライザーを使用する
  • XmlInclude が不要になるように、型が同じアセンブリにあることを確認してください (yuck)
  • Bar を変更してシリアライズ可能にします (yuck)
  • この種のメソッドを持つことは避けてください。つまり、DTO タイプのオブジェクトのみをシリアライズし、そのような機能を別の場所に持つことによってです。
  • これは卑劣でハックです... Bar 型と同じアセンブリシリアライズ可能なダミー クラスをインクルードし、代わりに XmlInclude を使用すると、シリアライザが満足するようになります。つまり、次のようになります。

例:

namespace BarStuff {
  //the serializer is perfectly happy with me
  public class DummyBar{}

  //the serializer doesn't like me
  public class Bar{
  ...
  }

  ...
}

using BarStuff;
namespace FooStuff {
  [XmlInclude(typeof(DummyBar))]
  public class Foo {
    public T GetBar<TBar, T>( string key ) where TBar : Bar<T> {
      ...
    }
  }
于 2010-09-15T02:54:44.543 に答える