1
    [Serializable]
    public class GraphViewModel : ViewModelBase
    {    
        public GraphViewModel()
        {
            //Constructor
        }

        public bool bool1 { get; set; }
        public bool bool2 { get; set; }
        public bool bool3 { get; set; }
        public ObservableCollection<Foo> Foos { get; set; }
    }

使用上面的示例类,我可以毫无问题地序列化并插入二进制数据库字段。当我反序列化时,一切正常,但速度很慢(从 3 到 25 秒)。注意:列表中只有 5 个项目。

我已将问题缩小到 ObservableCollection。当我设置属性 [XmlIgnore] 时,反序列化的速度非常好,因为列表不包含在 xml 输出中。

我更喜欢使用 ObservableCollection 并改进我的设置以更有效地处理这种情况,但无法在线找到解决方案。

编辑: 我尝试了以下属性:

[XmlArray(ElementName = "Foos")]
[XmlArrayItem(ElementName = "Foo")]
public ObservableCollection<Foo> Foos { get; set; }

它使 Xml 更具可读性,但不会提高反序列化速度。

4

1 回答 1

2

反序列化速度很可能是由于可观察集合引发的事件。

在这种情况下,我所做的是将有问题的属性标记为 XMLIgnore,然后添加一个可序列化但类型更简单的伪属性,例如 List<>。在新属性的 getter 和 setter 中,只需将数据移入和移出不可序列化的属性。

编辑:

我意识到最初的建议与当前的反序列化具有相同的性能损失,因此我修改了概念以允许将一系列记录添加到可观察集合中,同时抑制否则会引发的事件。

首先,我们需要创建一个继承自 ObservableCollection 的特殊类:

public class FooCollection : ObservableCollection<Foo>
{
}

在这个类中,我们需要添加一个允许我们添加一系列记录的方法,在本例中为 List<> 形式,并表明我们不希望在添加记录时发生通知:

    private bool m_fSuppressNotifications;

    public void AddRange(List<Foo> cItems)
    {
        if ((cItems == null) || (cItems.Count == 0)) {
            this.Clear();
        } else {
            try
            {
                // Keep events from being fired
                m_fSuppressNotifications = true;
                foreach (var oFoo in cItems)
                {
                    this.Add(oFoo);
                }
            }
            finally
            {
                m_fSuppressNotifications = false;
                // Raise the event to notify any listeners that the data has changed
                this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset))
            }
        }
    }

最后,我们需要覆盖 CollectionChanged 相关的元素并抑制或手动执行相关事件:

    public override event NotifyCollectionChangedEventHandler CollectionChanged;

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        // Prevent infinite loop that could occur if handler changes the collection
        using (BlockReentrancy())
        {
            if (!m_fSuppressNotifications)
            {
                // Get the current event
                var oCollectionChangedEvent = this.CollectionChanged;
                if (oCollectionChangedEvent != null)
                {
                    foreach (EventHandler oHandler in oCollectionChangedEvent.GetInvocationList())
                    {
                        // Execute the handler
                        oHandler(this, e);
                    }
                }
            }
        }
    }

最后,我们需要稍微更改 GraphViewModel 内部的实现,以抑制 FooCollection 的序列化并添加一个可序列化的 List<> 属性:

public class GraphViewModel
{
    [XmlIgnore]
    public FooCollection Foos { get; set; }

    [XmlArray(ElementName = "Foos")]
    [XmlArrayItem(ElementName = "Foo")]
    public List<Foo> FoosSerializable
    {
        get
        {
            return this.Foos.ToList<Foo>();
        }
        set
        {
            this.Foos.AddRange(value);
        }
    }

}
于 2013-01-02T19:42:01.177 回答