【问题标题】:Serializing WPF DrawingBrush with protobuf-net problems使用 protobuf-net 问题序列化 WPF DrawingBrush
【发布时间】:2012-05-08 19:50:30
【问题描述】:

需要序列化一些包含 DrawingBrush 的 BL 结构。我把它改写如下:

[ProtoContract]
public class BaseProtoBuf : INotifyPropertyChanged, IFormattable
{
    [ProtoMember(1)]
    public string ID { get; set; }
    // Bunch of properties of .net primitive types
    // ..
    private DrawingBrush _geometry;
    [ProtoMember(9)]
    [Browsable(false)]
    public DrawingBrush Geometry
    {
            get { return _geometry; }
            set
            {
                _geometry = value; 
                ScaleDrawing();
            }
    }
}
[ProtoContract]
[ProtoInclude(1, typeof(string))]
// All other includes
[ProtoInclude(9, typeof(DrawingBrush)]
public class DerivedProtoBuf : BaseProtoBuf, ICloneable
{        
    // Some additional properties of primitive types, annotated starting with ProtoMember 10 and so on
}

要序列化我正在执行以下代码:

const string fileName = "Protobuf.bin";
using (var file = File.Create(fileName))
{
    file.Position = 0;
    var testBase = new BaseProtoBuf
                                   {
                                      Height = 100,
                                      Width = 100,
                                      Name = "Test 1",
                                      OffsetX = 200,
                                      OffsetY = 200,
                                      Geometry = sourceList[0].Geometry // some not-null DrawingBrush
                                  };
    Serializer.Serialize(file, testBase);
    file.Position = 0;
    var restored = Serializer.Deserialize<BaseProtoBuf>>(file);
}
}

我需要序列化 ​​Derived 类对象,但在 Base 序列化期间我得到 “找不到合适的默认 DrawingBrush 编码”。认为这是因为 DrawingBrush 对于某些对象可以为空,但在测试中它不是。正确序列化的任何解决方法 1) 具有非空 DrawingBrush 的基础对象 2) 具有空 DrawingBrush 的派生对象?提前致谢。

【问题讨论】:

    标签: .net wpf serialization protobuf-net


    【解决方案1】:

    为简单 WPF 画笔序列化正确的 RuntimeTypeModel 配置:

    RuntimeTypeModel.Default.Add(typeof(Brush), false)
                   .AddSubType(300, typeof(SolidColorBrush));
    RuntimeTypeModel.Default.Add(typeof(SolidColorBrush), false)
                    .Add("Color");
    RuntimeTypeModel.Default.Add(typeof(Color), false)
                    .Add("A", "R", "G", "B"); // needed for proper color serialization
    RuntimeTypeModel.Default.Add(typeof(SolidColorBrush), false)
            .Add("Color");
    RuntimeTypeModel.Default.Add(typeof(DrawingBrush), false)
            .Add("Stretch", "Drawing");
    RuntimeTypeModel.Default.Add(typeof(Drawing), false)
            .AddSubType(100, typeof(DrawingGroup))
            .AddSubType(200, typeof(GeometryDrawing));
    RuntimeTypeModel.Default.Add(typeof(DrawingGroup), false)
            .Add("Children");
    RuntimeTypeModel.Default.Add(typeof(Pen), false)
            .Add("Brush", "Thickness", "LineJoin");
    RuntimeTypeModel.Default.Add(typeof(GeometryDrawing), false)
           .Add("Brush", "Geometry", "Pen");
    

    【讨论】:

    • eesh 看起来像.... “有趣” ;p 很高兴有办法通过。小反馈;由于“varint”编码的工作原理,为子类型(300/200/100)使用较小的标记号应该可以节省几个字节。不过,没有什么令人瞠目结舌的。
    【解决方案2】:

    DrawingBrush 不能立即序列化,因为合同没有定义。这里有各种选项:

    • 如果类型相当简单,您可以在运行时通过 RuntimeTypeModel 配置合约,根据需要添加属性/子类型等
    • 在某些情况下,可能首选使用“代理” - 一种具有双向转换运算符的类型,用作动态 DTO - 同样,可以通过 RuntimeTypeModel 指定代理; “代理”让您可以使用现有模型,但根据需要交换 DTO 类型
    • 否则,请考虑在模型中避免使用特定于框架的类型,而只使用包含所需信息的 DTO 类型。从中构建框架在运行时所需的值

    【讨论】:

    • 感谢您的快速回答,我想我需要选择选项#1,因为需要“按原样”存储对象(实际上,我构建它们得到的是来自外部源的纯 xml使用一堆字符串,因此创建托管对象然后将它们序列化回字符串不是一种选择)以便之后快速加载。您能指出一些复杂框架数据类型的合约配置示例吗?
    • 我已经检查了整个存储库并对序列化程序进行了一些研究,但由于 IProtoSerializer 是内部的,我猜它不应该在库之外实现。还尝试为基础类型手动创建 RuntimeTypeModel,但它也没有帮助(编译中的错误 - BuildAllSerializers:MetaType 对象具有 null 序列化程序,导致 没有为类型定义序列化程序:System.Windows.Media.DrawingBrush错误)。
    • @Jaded RuntimeTypeModel.Default.Add(typeof(DrawingBrush), false).Add("x", "y", "z");例如 - 更微妙的设置是可能的。
    • 谢谢,这种方法可能正是我所需要的。我已经手动设置了 DrawingBrush,它会序列化所有属性。唯一的问题是引发 TargetInvocationException 的反序列化。我一步一步调试了这个过程,发现问题出在编码上——在 ParseableSerializer 中调用 Geometry 的 Parse 方法(读取方法,第 57 行)源字符串是“F1M0,499938;0,499959L23,8304;0,499959 23 ,8304; 18,4977 0,499938; 18,4977 0,499938; 0,499959z“何时(在我的区域设置?)是”F1M0.499938,0.49995959 23.8304,18.4977 0.499938.4977 0.499938,0.499959 z"
    • @Jaded 两端的语言环境是什么?
    猜你喜欢
    • 1970-01-01
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-26
    • 1970-01-01
    相关资源
    最近更新 更多