输入' System.Windows.Input.Cursor'无法序列化

时间:2015-09-17 03:47:10

标签: c# wpf serialization datacontractserializer

我想序列化datacontract 这是代码datacontract

webpages

当我序列化到这段代码时

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

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

修改

这是序列化之前的结果datacontract对象

images

感谢

2 个答案:

答案 0 :(得分:0)

您无法序列化游标。如果它是使用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);

答案 1 :(得分:0)

我能够使用以下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可以保存。但是,可以使用standard set of cursors将游标转换为其名称,该名称可以是CursorConverter中的名称,也可以是加载游标的文件名。您可以利用这一事实在序列化期间用data contract surrogate替换CursorSO link存储游标的名称,而不是游标本身。反序列化时,代理将尝试从名称中重新加载游标:

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>

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