我有一个我正在序列化的课程:
using (FileStream fileStreamWriter = new FileStream(fileName, FileMode.Create))
{
var dataContractSerializer = new DataContractSerializer(typeof(ClassToBeSerialized));
dataContractSerializer.WriteObject(fileStreamWriter, btChartGroupList);
fileStreamWriter.Close();
}
在我将Brush
类型的属性(称为AreaBrush
)添加到ClassToBeSerialized
类之前,这样可以正常工作。此AreaBrush
属性可以是SolidBrush
,LinearGradientBrush
或RadialGradientBrush
。在序列化期间,DataContractSerializer
抛出:
键入' System.Windows.Media.MatrixTransform'使用数据合同名称' MatrixTransform:http://schemas.datacontract.org/2004/07/System.Windows.Media'不是预期的。如果您正在使用DataContractSerializer或者将任何静态未知的类型添加到已知类型列表中,请考虑使用DataContractResolver - 例如,使用KnownTypeAttribute属性或将它们添加到传递给序列化程序的已知类型列表中。
关于如何让它发挥作用的任何想法?
我和BrushConverter
一起玩,但没有那么好运。
我想我可以添加所有3种类型的画笔作为属性,但我希望有更好的解决方案。
编辑: 在VMaleev的帮助下,我最终做到了这一点:
[IgnoreDataMember]
public Brush AreaBrush
{
get { return _areaBrush; }
set
{
SetProperty(ref _areaBrush, value, () => AreaBrush);
}
}
[DataMember]
public string AreaBrushText
{
get
{
using (StringWriter sw = new StringWriter())
{
XamlWriter.Save(AreaBrush, sw);
string s = sw.ToString();
return sw.ToString();
}
}
set
{
AreaBrush = (Brush)XamlReader.Parse(value);
}
}
答案 0 :(得分:2)
你不能简单地这样做。我建议您将Brush属性标记为[XmlIgnore],并使用XamlWriter和XamlReader分别对其进行序列化和反序列化:
// example of writing
using (var outfile = File.CreateText("Brush.xaml"))
{
XamlWriter.Save(brush, outfile);
}
// example of reading
using (Stream s = File.OpenRead("Brush.xaml"))
{
Brush b = XamlReader.Load(s);
}
查看this主题以获取更多信息
答案 1 :(得分:2)
您可以通过将任意WPF元素包装在实现IXmlSerializable
的类中来序列化它:
[DataContract]
class ClassToBeSerialized
{
public LinearGradientBrush Brush { get; set; }
[DataMember(Name = "Brush")]
private XamlSerializationWrapper<LinearGradientBrush> BrushSerializer
{
get { return new XamlSerializationWrapper<LinearGradientBrush>(Brush); }
set { Brush = value.Element; }
}
}
class XamlSerializationWrapper<TElement> : IXmlSerializable
{
public TElement Element { get; private set; }
protected XamlSerializationWrapper()
{
}
public XamlSerializationWrapper(TElement element)
{
this.Element = element;
}
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
// this is a bit circuitous, but XamlReader.Load closes the reader for some reason
var element = (XElement)XElement.ReadFrom(reader);
Element = (TElement)XamlReader.Parse(element.Elements().Single().ToString());
}
public void WriteXml(XmlWriter writer)
{
XamlWriter.Save(Element, writer);
}
}
示例XML:
<?xml version="1.0" encoding="utf-16"?>
<ClassToBeSerialized xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/WpfSerialization">
<Brush>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#FF000000" Offset="0" />
<GradientStop Color="#FFFFFFFF" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Brush>
</ClassToBeSerialized>
使用示例:
public static string ToXml(ClassToBeSerialized cts)
{
var dcs = new DataContractSerializer(typeof(ClassToBeSerialized));
using (var sb = new StringWriter())
{
using (var xs = XmlWriter.Create(sb, new XmlWriterSettings() { Indent = true }))
{
dcs.WriteObject(xs, cts);
}
return sb.ToString();
}
}
public static ClassToBeSerialized FromXml(string xml)
{
var dcs = new DataContractSerializer(typeof(ClassToBeSerialized));
return (ClassToBeSerialized)dcs.ReadObject(XmlReader.Create(new StringReader(xml)));
}