私はプラグインベースのホストアプリケーションを持っています。その設定はデータコントラクトとして記述されています:データコントラクト:デシリアライズ時に不明な型を無視する
[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;
}
それはひどいかもしれませんが、それは動作します。 :)
質問するのではなく、Managed Extensibility Framework (MEF)を使用することができます。問題は、未知の型を含むオブジェクトグラフの逆シリアル化です。 – Dennis