2015-11-26 18 views
5

C#でオブジェクトをXMLシリアル化/逆シリアル化しようとしています。キャッチは、このオブジェクトが、直列化を呼び出すコードと同じアセンブリ内で宣言されていない型であることです。代わりに、実行時に動的にロードされるアセンブリから来るので、コンパイル時に直列化を呼び出すコードが不明です。C#Xmlシリアル化:他のアセンブリから来るオブジェクトをシリアル化できません。

私はシリアライズしようとしているタイプはこれです:私は前に述べたように、私はこのオブジェクトをデシリアライズ/シリアライズしようとするために使用しているコードがないアセンブリ内に位置しています

//Assembly = P.dll 
namespace EDFPlugin.Plugin1 
{ 
    [Serializable] 
    [XmlRoot(Namespace = "EDFPlugin.Plugin1")] 
    [XmlInclude(typeof(Options))] 
    public class Options 
    { 
     private string _username; 
     private string _password; 

     public string Username { 
      get { return _username; } 
      set { _username = value;} 
     } 

     public string Password 
     { 
      get { return _password; } 
      set { _password = value; } 
     } 
    } 
} 

実行時にP.dllが動的にロードされるため、コンパイル時にOptionsタイプについて知っています。それにもかかわらず、私はこのコードを使用することにより、正しくタイプをシリアル化するための管理:

//Assembly = A.exe (doesn't know about P.dll at compile time) 
object value = GetOptions() //the actual type returned by this method is EDFPlugin.Plugin1.Options !! 
XmlSerializer valueSerializer = new XmlSerializer(value.GetType()); 
valueSerializer.Serialize(writer, value); 

基本的に、あなたが見ることができるように、GetType()を呼び出すことによって、私はコンパイル時にOptionsタイプの知識を持っていないという問題を回避することができ、すべて正常に動作します。私は逆シリアル化しようとすると、

問題が発生する:

//Assembly = A.exe (doesn't know about P.dll at compile time) 
XmlSerializer valueSerializer = new XmlSerializer(typeof(object)); //have to use object, as I don't know the type in question... 
object value = valueSerializer.Deserialize(reader); //throws exception 

私は事前に質問でタイプを知らないので、私は基本的にない正しくセットアップできXmlSerializer。上記のコードに示すように、一般的なobjectを使用して、例外を生成します。

"<Options xmlns='EDFPlugin.Plugin1'> was not expected." 

どのように私はこの問題を解決することができますか?

+0

一致する型を定義する必要があります(必ずしも同じではありませんが、成功した直列化を成功させるには名前と必要なプロパティを提示する必要があります)。[関連する質問](http://stackoverflow.com/q/26368990/1997232)を参照してください。デシリアライゼーションは、どのような方法でもタイプを見つけることができない場合には、それが逆シリアル化できない場合はすべて反映されます。 * EDFPluginsを模倣する必要があります。Plagin1'を 'A.exe'に追加しました。 – Sinatr

+0

@Sinatr:情報ありがとう。残念ながら、私はそれを行うことはできません。私のプログラムは一連のプラグインを動的に読み込み、質問に表示されているような直列化可能なオプションオブジェクトを公開することができます。私のプログラムはこれらのオプションを自動的に保存/ロードできるはずです。しかし、私はオプションのオブジェクトで特定のプラグインがどのフィールドを公開するかについての事前知識は持っていません –

+1

'p.dll'がまだロードされていないときにデシリアライズについて話していると思いました。ロードされている場合は、読み込まれたアセンブリから型を取得する(ロード方法を無視する)ことは難しくありません(@ Ksv3nの答えに従って)。プラグインの場合、いくつかのAPIを公開するので、configsはプラグインによって保存されます(または、プラグインはすべての情報を提供します)。例えば。それぞれのプラグインが実装しなければならない 'GetTypeToSerialize()'メソッドを作成し、今タイプを取得できます。 – Sinatr

答えて

3

A.EXEは

だからA.EXEは、実行時にそれを知っているならば、あなたはEDFPlugin.Plugin1

動的にロード行うことができshoud(コンパイル時にP.dllについて知りません)どの程度:

XmlSerializer valueSerializer = new XmlSerializer(Type.GetType("EDFPlugin.Plugin1.Options")); 
object value = valueSerializer.Deserialize(reader); 

しかし、私はどちらかその型名がわからない場合は何?

オプションクラスを他のクラスと区別するためにカスタムインターフェイスを配置することをお勧めします。動的にフィルターをかけてXmlSerializerで読み込むことができます。

その後
public interface IAmPlugin 
{ 

} 

public class Options: IAmPlugin 
{ 
     ...... 
} 

Assembly assembly = ... // Your Assemblie which contains plugin 

// XmlSerializer needs all possible types to Deserialize an interface 
var possibleTypes = assembly.GetTypes().Where(t => t.IsClass && t.IsAssignableFrom(typeof(IAmPlugin))).ToArray(); 

XmlSerializer serializer = new XmlSerializer(typeof(IAmPlugin), possibleTypes); 
object value = valueSerializer.Deserialize(reader); 

これはオプションクラスに空のpublicコンストラクタを前提としています。

なぜ属性ではなくインターフェイスですか? XmlSerializerは複数のインターフェイスタイプのみを処理するためです。

+0

しかし、typenameもわからないのですが?アイデアは、A.exeが保存/ロードできるはずの直列化可能なオブジェクトを公開できる一連のプラグインがあることです。この場合、それはオプションタイプですが、それは他のものかもしれませんが、私は事前に分かりません。私は[XmlRoot(Namespace = "EDFPlugin.Plugin1")]タグがそれを処理すると思っていました(実際にはXMLに名前空間を書き込みます)が、明らかにそうではありません。 –

+0

私は更新を行いました。 – Ksv3n

+1

ありがとうございます.XmlSerializerで複数の型を指定して "試してみる"ことができませんでした。 –

関連する問題