2011-12-12 42 views
5

私はプラグインベースのホストアプリケーションを持っています。その設定はデータコントラクトとして記述されています:データコントラクト:デシリアライズ時に不明な型を無視する

[DataContract(IsReference = true)] 
public class HostSetup 
{ 
    [DataMember] 
    public ObservableCollection<Object> PluginSetups 
    { 
     get 
     { 
      return pluginSetups ?? (pluginSetups = new ObservableCollection<Object>()); 
     } 
    } 
    private ObservableCollection<Object> pluginSetups;   
} 

いずれのプラグインも独自の設定タイプを持っています。 E.のグラム:

[DataContract(IsReference = true)] 
public class Plugin1Setup 
{ 
    [DataMember] 
    public String Name { get; set; } 
} 

と実行時に

[DataContract(IsReference = true)] 
public class Plugin2Setup 
{ 
    [DataMember] 
    public Int32 Percent { get; set; } 
    [DataMember] 
    public Decimal Amount { get; set; } 
} 

、ユーザーが設定したホストとプラグインのような方法:次に

 var obj = new HostSetup(); 
     obj.PluginSetups.Add(new Plugin1Setup { Name = "Foo" }); 
     obj.PluginSetups.Add(new Plugin2Setup { Percent = 3, Amount = 120.50M }); 

は、私のアプリケーションが保存されているそのDataContractSerializerを使用して設定します。プラグイン型は既知の型としてシリアライザのコンストラクタに渡されました。

質問です。
ユーザーは物理的に「Plugin2」でアセンブリを削除してから、アプリケーションを起動します。
したがって、ホストが利用可能なプラグインのリストを受け取ると、それはシリアライズされた「Plugin2Setup」インスタンスについては何も知りません。

私はこのインスタンスを無視して、 "Plugin2"の設定をせずに作業できるようにします。
これを行うにはエレガントな方法はありますか?
私は、文字列にシリアライズデータコントラクトとしてプラグイン設定を保存することができます

public ObservableCollection<String> PluginSetups 

を、それは便利と醜いではありません。

編集1
問題がインスタンスをhostsetupをデシリアライズし、シリアライズさPlugin2Setupインスタンスを無視する方法です。

編集2
私の現在のソリューションは、次のとおりです。

[DataContract(IsReference = true)] 
public class PluginSetupContainer 
{ 
    [DataMember] 
    private String typeName; 
    [DataMember] 
    private String rawData; 

    [OnSerializing] 
    private void OnSerializing(StreamingContext context) 
    { 
     if (SetupParameters != null) 
     { 
      using (var writer = new StringWriter()) 
      using (var xmlWriter = new XmlTextWriter(writer)) 
      { 
       var setupParametersType = SetupParameters.GetType(); 
       var serializer = new DataContractSerializer(setupParametersType); 
       serializer.WriteObject(xmlWriter, SetupParameters); 

       xmlWriter.Flush(); 

       typeName = setupParametersType.AssemblyQualifiedName; 
       rawData = writer.ToString(); 
      } 
     } 
    } 

    [OnSerialized] 
    private void OnSerialized(StreamingContext context) 
    { 
     ClearInternalData(); 
    } 

    [OnDeserialized] 
    private void OnDeserialized(StreamingContext context) 
    { 
     if (!String.IsNullOrEmpty(typeName) && !String.IsNullOrEmpty(rawData)) 
     { 
      var setupParametersType = Type.GetType(typeName, false); 
      if (setupParametersType != null) 
      { 
       using (var reader = new StringReader(rawData)) 
       using (var xmlReader = new XmlTextReader(reader)) 
       { 
        var serializer = new DataContractSerializer(setupParametersType); 
        SetupParameters = serializer.ReadObject(xmlReader); 
       } 
      } 

      ClearInternalData(); 
     } 
    } 

    private void ClearInternalData() 
    { 
     typeName = null; 
     rawData = null; 
    } 

    public Object SetupParameters { get; set; } 
} 

[DataContract(IsReference = true)] 
public class HostSetup 
{ 
    [DataMember] 
    public ObservableCollection<PluginSetupContainer> PluginSetups 
    { 
     get 
     { 
      return pluginSetups ?? (pluginSetups = new ObservableCollection<PluginSetupContainer>()); 
     } 
    } 
    private ObservableCollection<PluginSetupContainer> pluginSetups; 
} 

それはひどいかもしれませんが、それは動作します。 :)

答えて

0

私は彼らの種類が登録されている理想的に、あなたが存在しているMyPluginCustomAttributeので、アセンブリのみに基づいて反射を利用してobj.PluginSetupsを初期化する必要があります

[DataContract(IsReference = true)] 
[MyPluginCustomAttribute] 
public class Plugin1Setup 
{ 
} 

とするときにアプリケーションの負荷のラインに何かを持っているべきだと思います。したがって、アセンブリの不足という問題はありません。また、または、「どのようにプラグインの設定を初期化する」「どのように利用可能なプラグインとその設定タイプのリストを受け取るために」されていない独自のMyPluginCustomAttribute

+0

質問するのではなく、Managed Extensibility Framework (MEF)を使用することができます。問題は、未知の型を含むオブジェクトグラフの逆シリアル化です。 – Dennis

関連する問題