【问题标题】:Clipboard + PresentationFramework = OutOfMemoryException?剪贴板 + PresentationFramework = OutOfMemoryException?
【发布时间】:2012-11-15 02:11:00
【问题描述】:

为什么System.Windows.Clipboard(PresentationCore.dll) 不友好 System.Windows.Thickness (PresentationFramework.dll) 但对 System.Windows.Point (WindowsBase.dll) 友好

using System;
namespace ConsoleApplication5 {
    class Program {
        /*
        * Add references to 
        * WindowsBase.dll (Point)
        * PresentationFramework.dll (Thickness)
        * PresentationCore.dll (Clipboard)
        */

        [STAThread]
        static void Main(string[] args)
        {
            Test myTest = new Test();
            System.Windows.Clipboard.SetData("myformat", myTest);
            // OutOfMemoryException
            Object myPastedTest = System.Windows.Clipboard.GetData("myformat");
        }
    }

    [Serializable]
    class Test
    {
        // COMMENT THE LINES BELLOW PresentationFramework TO WORK OK!
        // PresentationFramework.dll
        //public System.Windows.Thickness MyThickness { get; set; } 
        public System.Windows.Media.Brush MyBrush { get; set; }

        // WindowsBase.dll
        public System.Windows.Point MyPoint { get; set; }

    }
}

【问题讨论】:

  • 剪贴板上有多少数据?
  • This answer 可能会为您提供解决方案,但我无法告诉您为什么剪贴板讨厌某些对象而不讨厌其他对象。我认为它与对象是否可序列化有关

标签: c# .net wpf clipboard


【解决方案1】:

Brush 类不可序列化并导致抛出 OutOfMemoryException(请参阅http://www.grumpydev.com/2009/09/05/system-outofmemoryexception-gotcha-using-clipboard-getdata-in-wpf/)。您也许可以将 Test 类序列化为 XAML 并将其放到剪贴板上,请参阅此链接以获取信息:

How can i serialize xaml "Brush"?

【讨论】:

    【解决方案2】:

    根据 msdn,PointSerializableAttribute,而 Thickness 没有。 SerializableAttribute 不会应用于班级成员。这就解释了为什么 Clipboard.SetData() 会静默失败,以及为什么 Clipboard.GetData() 返回垃圾。

    您可以围绕Thickness 编写一个实现ISerializable 并具有SerializableAttribute 的包装器,如下所示:

    [Serializable]
    public struct SerializableThickness : ISerializable
    {
        public Thickness Data;
    
        public SerializableThickness(Thickness t)
        {
            Data = t;
        }
    
        #region ISerializable
        private const string LeftField = "LeftField";
        private const string TopField = "TopField";
        private const string RightField = "RightField";
        private const string BottomField = "BottomField";
    
        private SerializableThickness(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                throw new ArgumentNullException("info");
    
            var enumerator = info.GetEnumerator();
            bool[] found = { false, false, false, false };
            double[] values = new double[4];
            while (enumerator.MoveNext() && !found.All(x => x))
            {
                switch (enumerator.Name)
                {
                    case LeftField:
                        found[0] = true;
                        values[0] = (double)enumerator.Value;
                    break;
    
                    case TopField:
                        found[1] = true;
                        values[1] = (double)enumerator.Value;
                    break;
    
                    case RightField:
                        found[2] = true;
                        values[2] = (double)enumerator.Value;
                    break;
    
                    case BottomField:
                        found[3] = true;
                        values[3] = (double)enumerator.Value;
                    break;
                }
            }
    
            if (!found.All(x => x))
                throw new SerializationException("Missing serializable members");
    
            Data = new Thickness(values[0], values[1], values[2], values[3]);
        }
    
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue(LeftField, Data.Left);
            info.AddValue(TopField, Data.Top);
            info.AddValue(RightField, Data.Right);
            info.AddValue(BottomField, Data.Bottom);
        }
        #endregion
    }
    

    【讨论】:

    • 如何序列化厚度?
    • @serhio,编写一个包含SerializableAttribute 的包装类。
    • @serhio,我添加了一个示例包装器。
    • 那么,复制 System.Windows 中的所有结构是您的想法吗?命名空间?刷子?其他的?...
    • @serhio,你错了。一些结构已经可以序列化:SizePoint,还有很多其他的。 Clipboard 仅适用于可序列化数据:An object must be serializable for it to be put on the Clipboard. To make a type serializable, mark it with the SerializableAttribute attribute. If you pass a non-serializable object to a Clipboard method, the method will fail without throwing an exception.(引用自 msdn.microsoft.com/en-us/library/637ys738.aspx)。除了使您的数据可序列化之外,别无他法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-07
    • 2010-09-11
    • 2010-11-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多