我有一個基於插件的主機應用程序。其設置被描述爲數據合同:數據合同:忽略未知類型的反序列化
[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;
}
可能是可怕的,但它的工作原理。 :)
問題不在於「如何得到可用的插件及其設置類型的列表」或「如何初始化插件設置」。問題是包含未知類型的對象圖的反序列化。 – Dennis