【问题标题】:Type 'System.Windows.Input.Cursor' cannot be serialized类型“System.Windows.Input.Cursor”无法序列化
【发布时间】:2015-09-17 03:47:09
【问题描述】:

我想序列化数据合同 这是代码数据合同

[Serializable]
//[DataContract(Name = "Shared", Namespace = "PJ")]
[DataContract]
[KnownType(typeof(System.Windows.Media.MatrixTransform))]
[System.Runtime.Serialization.KnownType(typeof(TPropHatchBrush))]
[System.Runtime.Serialization.KnownType(typeof(System.Windows.Input.Cursor))]
public class TPropHatchBrush : TPropBrush, ICloneable
{
    [DataMember]
    public UInt32 uColor = 0xFFFE0606;
    [DataMember]
    public double Opacity = 1;
    [DataMember]
    public VisualBrush theBrush = new VisualBrush();
    [DataMember]
    public Grid grd = new Grid();
    [DataMember]
    public Path path = new Path();
    [DataMember]
    public SolidColorBrush blackBrush = new SolidColorBrush();
    //[DataMember]
    //public BitmapSource bmp = null;


    public Color Color
    {
        get
        {
            return TUtility.ColorFromUInt32(uColor);
        }
        set
        {
            uColor = TUtility.ColorToUInt32(value);
        }
    }
    //
    public TPropHatchBrush()
    {
        BrushType = BrushType.Hatch;

        path.Data = Geometry.Parse("M 0 0 L 15 15");
        blackBrush.Color = Colors.Black;
        path.Stroke = blackBrush;
        //path.StrokeThickness = 3;
        path.Fill = blackBrush;
        grd.Children.Add(path);
        theBrush.Viewport = new Rect(0, 0, 0.15, 0.15);
        theBrush.TileMode = TileMode.Tile;
        // Set Visual of VisualBrush
        //theBrush.Visual = grd;



    }
    override public Brush getBrush()
    {
        SolidColorBrush br = new SolidColorBrush(Color);
        br.Opacity = Opacity;
        return br;
    }
    /*override public bool FromArrayByte(byte[] val)
    {
        TPropHatchBrush tbrush = (TPropHatchBrush)CSerialization.dataContractDeserializer(val, typeof(TPropHatchBrush));
        return false;
    }*/
    public override bool FromArrayByte(byte[] val)
    {
        TPropHatchBrush tbrush = (TPropHatchBrush)CSerialization.dataContractDeserializer(val, typeof(TPropHatchBrush));
        return false;
    }
    public byte[] ToArrayByte()
    {
        //return CSerialization.saveSerializableObject(this);
        //CSerialization.dataContractSerializer(@"e:\test.xml", this);
        return CSerialization.dataContractSerializer(this);
    }
    override public void CopyFrom(TPropBrush to, TPropBrush from)
    {
        ((TPropHatchBrush)to).BrushType = ((TPropHatchBrush)from).BrushType;
        ((TPropHatchBrush)to).uColor = ((TPropHatchBrush)from).uColor;
        ((TPropHatchBrush)to).Opacity = ((TPropHatchBrush)from).Opacity;
    }
    public object Clone()
    {
        TPropHatchBrush to = new TPropHatchBrush();
        CopyFrom(to, this);
        return to;
    }
    override public bool FromBrush(Brush br)
    {
        SolidColorBrush sbr;
        try
        {
            sbr = (SolidColorBrush)br;
            Color = sbr.Color;
            Opacity = sbr.Opacity;
        }
        catch
        {
            return false;
        }
        return false;
    }
}

当我序列化到这段代码时

public static byte[] dataContractSerializer(object obj)
    {
        MemoryStream ms = new MemoryStream();
        DataContractSerializer ser = new DataContractSerializer(obj.GetType());
        XmlDictionaryWriter binaryDictionaryWriter = XmlDictionaryWriter.CreateBinaryWriter(ms);
        ser.WriteObject(binaryDictionaryWriter, obj);
        binaryDictionaryWriter.Flush();
        byte[] data = ms.ToArray();
        return data;
    }

我有错误,错误警告是

Additional information: Type 'System.Windows.Input.Cursor' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute.  If the type is a collection, consider marking it with the CollectionDataContractAttribute.  See the Microsoft .NET Framework documentation for other supported types.

如何解决这个问题? 首先我得到一个错误 MatrixTransform,所以我在 Input.Cursor 中使用 knowntype MatrixTransform 和错误,所以我使用 knowntype Input.Cursor 并且仍然错误。

编辑

这是序列化之前的结果数据合约对象

谢谢

【问题讨论】:

  • 您的班级似乎没有System.Windows.Input.Cursor 属性。此外,从未定义基类TPropBrush。你能在 c# 中创建一个Minimal, Complete, and Verifiable example 你的问题,将你的类精简到演示问题的最简单版本吗?您可以将Data Contract Surrogates 用于Cursor
  • 是的,我没有System.Windows.Input.Cursor。但是当我在没有错误System.Windows.Input.Cursor 的情况下进行序列化时,另一个数据合同是有效的。 ,只有这个数据合同我有一个错误。 @dbc
  • 检查您使用的其他类型,例如 TPropBrush。

标签: c# wpf serialization datacontractserializer


【解决方案1】:

您不能序列化游标。如果光标的名称是标准类型之一,您可以使用 ToString() 方法序列化它,并使用 CursorConverter 类对其进行反序列化。

     String cursorName = System.IO.File.ReadAllText("I:\\cursor.txt");
     CursorConverter cnv = new CursorConverter();
     Cursor c = (Cursor) cnv.ConvertFromString(cursorName);

如果您的光标存在于文件中,那么您可以从该文件中获取 byte[] 并将其序列化。然后在反序列化时,使用它的构造函数从 byte[] 创建一个 MemoryStream,并使用 Cursor 的构造函数从该内存流中加载 Cursor。

    byte[] cursorBytes = ...
    MemoryStream ms = new MemoryStream(cursorBytes);
    Cursor c1 = new Cursor(ms);

【讨论】:

    【解决方案2】:

    我能够通过以下minimal, complete, and verifiable 测试用例重现您的问题:

    [DataContract]
    public class TPropHatchBrush : IDisposable
    {
        System.Windows.Input.Cursor cursor;
    
        [DataMember]
        public System.Windows.Input.Cursor Cursor { get { return cursor; } set { cursor = value; } }
    
        #region IDisposable Members
    
        public void Dispose()
        {
            var oldCursor = Interlocked.Exchange(ref this.cursor, null);
            if (oldCursor != null)
                oldCursor.Dispose();
        }
    
        #endregion
    }
    

    问题在于Cursor 类根本无法序列化——加载后没有API 可以保存它。但是,可以使用CursorConverter 将游标转换为其名称,该名称可以是来自standard set of cursors 的名称,也可以是加载游标的文件名。您可以利用这一事实在序列化期间将Cursor 替换为存储游标名称而不是游标本身的data contract surrogate。反序列化时,代理会尝试从名称重新加载游标:

    public class CursorDataSurrogate : IDataContractSurrogate
    {
        [DataContract(Namespace = "")]
        class CursorName
        {
            [DataMember]
            public string Name { get; set; }
        }
    
        #region IDataContractSurrogate Members
    
        public object GetCustomDataToExport(Type clrType, Type dataContractType)
        {
            throw new NotImplementedException();
        }
    
        public object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType)
        {
            throw new NotImplementedException();
        }
    
        public Type GetDataContractType(Type type)
        {
            if (type == typeof(System.Windows.Input.Cursor))
                return typeof(CursorName);
            return type;
        }
    
        public object GetDeserializedObject(object obj, Type targetType)
        {
            if (obj is CursorName)
            {
                try
                {
                    return (System.Windows.Input.Cursor)TypeDescriptor.GetConverter(typeof(System.Windows.Input.Cursor)).ConvertFromInvariantString(((CursorName)obj).Name);
                }
                catch (Exception ex)
                {
                    // ArgumentException or Win32Exception could be generated if file is missing or name is invalid.  Handle here, or pass on?
                    throw;
                }
            }
            return obj;
        }
    
        public void GetKnownCustomDataTypes(Collection<Type> customDataTypes)
        {
            throw new NotImplementedException();
        }
    
        public object GetObjectToSerialize(object obj, Type targetType)
        {
            if (obj is System.Windows.Input.Cursor)
            {
                return new CursorName { Name = TypeDescriptor.GetConverter(typeof(System.Windows.Input.Cursor)).ConvertToInvariantString(obj) };
            }
            return obj;
        }
    
        public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
        {
            throw new NotImplementedException();
        }
    
        public System.CodeDom.CodeTypeDeclaration ProcessImportedType(System.CodeDom.CodeTypeDeclaration typeDeclaration, System.CodeDom.CodeCompileUnit compileUnit)
        {
            throw new NotImplementedException();
        }
    
        #endregion
    }
    

    然后,在您的方法 dataContractSerializer 中,像这样使用它:

            var ser = new DataContractSerializer(obj.GetType(), new Type[] { }, Int32.MaxValue, false, false, new CursorDataSurrogate());
    

    由此生成的 XML 如下所示:

    <TPropHatchBrush xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Question32622276">
        <Cursor xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Windows.Input">
            <Name xmlns="">IBeam</Name>
        </Cursor>
    </TPropHatchBrush>
    

    请注意,如果游标不存在,按名称加载游标的方法可能会引发异常 - 例如因为加载它的文件不再存在。您可能需要修改代理来处理此问题,而不仅仅是重新抛出异常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-23
      • 1970-01-01
      • 2010-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-27
      相关资源
      最近更新 更多