简体   繁体   English

使用`DataContractSerializer`序列化包含WPF Brush的类

[英]Serializing a class containing a WPF Brush using `DataContractSerializer`

I have a class that I am serializing like: 我有一个要序列化的类,例如:

using (FileStream fileStreamWriter = new FileStream(fileName, FileMode.Create))
{
    var dataContractSerializer = new DataContractSerializer(typeof(ClassToBeSerialized));
    dataContractSerializer.WriteObject(fileStreamWriter, btChartGroupList);
    fileStreamWriter.Close();
}

This works fine until I add a property of type Brush (called AreaBrush ) to the ClassToBeSerialized class. 直到我将类型Brush的属性(称为AreaBrush )添加到ClassToBeSerialized类,该方法ClassToBeSerialized This AreaBrush property could be a SolidBrush , LinearGradientBrush or a RadialGradientBrush . AreaBrush属性可能是一个SolidBrushLinearGradientBrushRadialGradientBrush During serialization, DataContractSerializer throws: 序列化期间, DataContractSerializer引发:

Type 'System.Windows.Media.MatrixTransform' with data contract name 'MatrixTransform: http://schemas.datacontract.org/2004/07/System.Windows.Media ' is not expected. 键入数据合同名称为MatrixTransform的“ System.Windows.Media.MatrixTransform”:不应为http://schemas.datacontract.org/2004/07/System.Windows.Media Consider using a DataContractResolver if you are using DataContractSerializer or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to the serializer. 如果您正在使用DataContractSerializer或将任何不是静态已知的类型添加到已知类型的列表中,请考虑使用DataContractResolver-例如,通过使用KnownTypeAttribute属性或将它们添加到传递给序列化程序的已知类型的列表中。

Any ideas on how I can get this to work? 关于如何使它起作用的任何想法? I played around with the BrushConverter but didn't have much luck with that. 我玩过BrushConverter但运气不佳。

I guess I could add all 3 types of brushes as properties but I am hoping for a better solution. 我想我可以将所有3种类型的笔刷都添加为属性,但是我希望有一个更好的解决方案。

EDIT: With the help of VMaleev I ended up doing this: 编辑:在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);
        }
    }

You cannot do that simply. 您不能简单地做到这一点。 I would recommend you to mark your Brush property as [XmlIgnore] and serialize and deserialize it separately using XamlWriter and XamlReader : 我建议您将Brush属性标记为[XmlIgnore],并分别使用XamlWriterXamlReader对其进行序列化和反序列化:

// 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);
}

View this topic for more information 查看主题以获取更多信息

You can serialize an arbitrary WPF element by wrapping it in a class which implements IXmlSerializable : 您可以通过将任意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);
    }
}

Example XML: 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>

Example use: 使用示例:

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)));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 实体未使用DataContractSerializer进行序列化 - Entities are not serializing using DataContractSerializer 使用DataContractSerializer序列化接口列表 - Serializing a List of Interfaces using the DataContractSerializer DataContractSerializer不是序列化继承ISerializable的类的成员 - DataContractSerializer not Serializing member of class that inherits ISerializable 使用DataContractSerializer序列化循环对象引用不起作用 - Serializing cyclic object references using DataContractSerializer not working 使用DataContractSerializer序列化从List &lt;&gt;继承的类不会序列化对象属性 - Serializing class inherited from List<> using DataContractSerializer does not serialize object properties 序列化包含自定义类的类 - Serializing a class containing a custom class 删除使用DataContractSerializer序列化的名称空间 - Removing namespaces serializing with DataContractSerializer 使用DataContractSerializer进行序列化时出现SecurityException - SecurityException when serializing with DataContractSerializer DataContractSerializer未序列化一个属性 - DataContractSerializer not serializing one property 使用 DataContractSerializer 进行序列化时如何忽略属性? - How can I ignore a property when serializing using the DataContractSerializer?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM