2017-07-06 12 views
0

私はプラグイン自体にいくつかのランタイムインスタンスを持つことができるプラグインシステムを持っています。これらのインスタンスは、持ち込まれる構成オブジェクトがさまざまなAPIを通じてプラグイン自体に利用可能になるように定義されます。AppDomainの基底型として派生型をシリアライズ

構成には、親アプリケーションが理解できる特定の部分が含まれていますが、プラグインがサブクラス化によって独自の部分を指定することが期待されています。

[Serializable] 
public class PluginConfiguration { 
    public string Name { get; set; } 
} 

public class MyPluginConfiguration : PluginConfiguration { 
    public string AccessToken { get; set; } 
} 

これは、部分的にそれだけでJSON/XMLの/ etcとして全体オブジェクトをシリアル化するための主な適用を可能にするよう技術的な理由です。共通の構成とプラグイン固有の構成の両方を維持するためにデータベースに追加します。

各プラグインは、それぞれのAppDomain内でホストされます。しかし、プライマリアプリドメインとプラグインからプラグイン設定を読み込もうとしているときに問題になっています(MarshalByRefObjectMyPluginConfigurationオブジェクトインスタンスを返します)

基本クラスにはいくつかの逐次化魔法を実行する方法はありますか?オブジェクトインスタンスがPluginConfigurationインスタンスとして直列化されることを保証するために、問題をMyPluginConfigurationインスタンスをシリアライズしている:

  • は、カスタム設定の種類は、彼らが[Serializable]あったとしても、彼らが持っていない[Serializable]
  • ではないかもしれません彼らのアセンブリは、とにかくプライマリアプリドメイン。

理想的には、実装をPluginConfigurationベースクラスに限定したいと思います。古い[Serializable]セマンティクスとAppDomainsは.Netの中で最も一般的な概念ではありません。プラグイン開発者からこれらの側面のいくつかを対処する必要がない場合は、それらを非表示にしたいと考えています。

答えて

0

あなた[Serializable]

注ごとに、バイナリシリアル化を使用:XMLはIXmlSerializable を持っているとJavascriptも異なっています。私はJSON.netが使用

[Serializable] 
public class PluginConfiguration : System.Runtime.Serialization.ISerializable 
{ 
    public string Name { get; set; } 
    public PluginConfiguration() 
    { 

    } 
    protected PluginConfiguration(SerializationInfo info, StreamingContext context) 
    { 
     if (info == null) 
      throw new System.ArgumentNullException("info"); 
     Name = (string)info.GetValue("Name", typeof(string)); 

    } 
    public virtual void GetObjectData(SerializationInfo info, StreamingContext context) 
    { 
     info.AddValue("Name", Name); 
    } 

} 

[Serializable] 
public class MyPluginConfiguration : PluginConfiguration 
{ 
    public string AccessToken { get; set; } 
    public MyPluginConfiguration() 
    { 

    } 
    protected MyPluginConfiguration(SerializationInfo info, StreamingContext context) :base(info, context) 
    { 

    } 

} 

private class PluginBinder : SerializationBinder 
{ 
    public override Type BindToType(string assemblyName, string typeName) 
    { 
     return typeof(PluginConfiguration); 
    } 
} 

の下に実施されるようなISerializableオブジェクトをシリアライズ信じる:

var c = new PluginConfiguration() { Name = "Name" }; 
var p = new MyPluginConfiguration() { Name = "Name", AccessToken = "MyToken" }; 

BinaryFormatter fmt = new BinaryFormatter(); 

MemoryStream cms = new MemoryStream(); 
fmt.Serialize(cms, c); 

cms.Position = 0; 
PluginConfiguration revc = fmt.Deserialize(cms) as PluginConfiguration; 

MemoryStream pms = new MemoryStream(); 
fmt.Serialize(pms, p); 
pms.Position = 0; 
MyPluginConfiguration prev = fmt.Deserialize(pms) as MyPluginConfiguration; 

//given a stream containing the serialization of MyPluginConfiguration 
// serailize it as a the known PluginConfiguration Type 

pms.Position = 0; 
fmt.Binder = new PluginBinder(); 
PluginConfiguration PluginFromCustomStream = fmt.Deserialize(pms) as PluginConfiguration; 
+0

私が必要になります何が 'fmt.Serialize(PMS、P)である。PluginConfigurationとしてfmt.Deserialize(PMS) '。プラグインアプリケーションドメインは、 'MyPluginConfiguration'型を使用して' Serialize'を行いますが、アプリケーションアプリケーションドメインは 'MyPluginConfiguration'を利用できないので、' Deserialize'には使用できません。代わりに 'Deserialize'に' PluginConfiguration'を使用させてください。 –

+0

これを行う方法を示すために、カスタムバインダーを回答に追加しました。 –

+0

それは役に立つと思う。これまでに 'SerializationBinder'型に遭遇したことはありませんでした。どのようにアプリケーションドメインを使用するために定義するのですか? –

関連する問題