というモジュールにこの単純なクラスがあるとしますClassLibrary1
。
[DataContract]
public class Class1
{
[DataMember]
private DataTable _data;
public void SetData(string key, object value)
{
_data = new DataTable("SomeName");
_data.Columns.Add("Key", typeof(String));
_data.Columns.Add("Value", value.GetType());
_data.Rows.Add(key, value);
}
}
と呼ばれる別のモジュールClassLibrary2
には、次のクラスがあります。
[DataContract]
public class Configuration
{
[DataMember]
private Class1 _obj;
public Configuration()
{
_obj = new Class1();
_obj.SetData("Key", MyEnum.Value2);
}
}
さらに、モジュールは public としてマークされていないClassLibrary2
という列挙型を定義しますMyEnum
。つまり、それはモジュールの内部にあります (ご覧のとおり、上記のコードで使用されています)。
現在、私のメイン モジュールでは、 に依存したくありませんがClassLibrary2
、実行時に動的にロードする必要があります。つまり、 を使用Assembly.LoadFrom
してから、使用する必要がある型を見つけ (私の単純な例では、"Configuration" という名前の型を検索するだけです)、 を使用してインスタンスを作成しますActivator.CreateInstance
。次に、次のようにインスタンスをシリアル化します。
var ser = new DataContractSerializer(config.GetType());
var outstream = new FileStream("c:\\test.xml", FileMode.Create);
ser.WriteObject(outstream, config);
outstream.Close();
これまでのところ、すべてが機能します。しかし、次のように逆シリアル化しようとすると:
var instream = new FileStream("c:\\test.xml", FileMode.Open);
var conf = ser.ReadObject(instream);
「列にArgumentException
は有効なデータ型が必要です」というメッセージが表示されます。次のいずれかの場合、これは発生しないことがわかりました。
- 代わりにメインモジュールで MyEnum を定義してください
- DataTable を単純なものに置き換えます
String key; Object value
- enum MyEnum の代わりに別のものを使用します (例: 文字列)
しかし、これらのオプションはどれも、私の実際のアプリケーションではあまり望ましいものではありません。最初のオプションは、互いに依存すべきではないモジュール間に強い結合を作成します。2 番目のオプションも可能ですが、少し手間がかかります (私はすでにクラス全体で DataTable を多くの場所で使用しており、シリアライゼーションを行う必要があることが最近わかりました)。3 番目のオプションもやや面倒です。
これを機能させる他の方法はありますか?また、コンストラクターを介して、およびクラス宣言の前にDataContractSerializer
追加することにより、シリアライザーの既知の型のリストに MyEnum を追加しようとしましたが、これは役に立ちませんでした。[KnownType(typeof(MyEnum))]
Configuration