问题
I have a class with an image that has to be (sometimes) serialized/deserialized according to the fact that the image is embedded or not.
[DataContract(IsReference = true)]
public class Data
{
[DataContract(IsReference = true)]
public class MyImage
{
[DataMember]
int WidthStorage
[DataMember]
int HeightStorage;
[DataMember]
public string strImageLocation;
[DataMember]
public Image ImageEmbedded = new Image();<----- not working null
public bool GetImage(Image image, int width, int height)
{
...
}
public void SetImageFSlocation(string _strImageLocation, int _widthStorage, int _heightStorage)
{
...
}
public void SetImageEmbedded(string strPathFilename, int _widthStorage, int _heightStorage)
{
...
}
}
So the problem is that despite putting
public Image ImageEmbedded = new Image();
ImageEmbedded is always null. So I put it in a constructor like
[DataContract(IsReference = true)]
public class MyImage
{
public MyImage()
{
ImageEmbedded = new Image();
}
...
but when I do that I get a serialization error. So what have I got to do? I would NOT turn Image to byte[] or other. I have chosen Datacontract serialization for I thought that it could serilize images. Thank you
回答1:
There is a major problem in your code: in WPF if you serialize an Image you serialize System.Windows.Controls.Image. So in short it doesn't make sense to serialize a control. Instead you might want to serialize a BitmapSource
but here again those can't be serialized so you have to turn them to byte[]
as already said.
[DataMember]
public byte[] bytesBitmapEmbedded;
and then simply change it to BitmapSource or byte[] through this:
bytesBitmapEmbedded = Converter.BitmapSource2ByteArray(bitmapSource);
or
bitmapSource = Converter.ByteArray2BitmapSource(bytesBitmapEmbedded);
with
public static class Converter
{
public static byte[] BitmapSource2ByteArray(BitmapSource bitmap)
{
using (var stream = new MemoryStream())
{
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
encoder.Save(stream);
return stream.ToArray();
}
}
public static BitmapSource ByteArray2BitmapSource(byte[] buffer)
{
using (var stream = new MemoryStream(buffer))
{
return BitmapFrame.Create(stream,
BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
}
}
回答2:
If your serialiser doesn't directly know how to convert a field's type then you'll be fighting against the wind. The easier solution is to revert to more primitive types that are in most languages; create a Data-Transfer Object. For example, I store quite a diverse amount of 1- 2-dimensional data with protobuf.net using something similar to this (edited for your needs):
[DataContract]
class ImageDTO
{
[DataMember(Order = 1)]
public int Width { get; set; }
[DataMember(Order = 2)]
public int Height { get; set; }
[DataMember(Order = 3)]
public ImageFormat Format { get; set; }
[DataMember(Order = 4)]
public byte[] Data { get; set; }
[DataMember(Order = 5)]
public string AltUrl { get; set; }
}
So in your case, you'd simply need to deal with the image format enum code and get the binary data from an image. See Fastest way to convert Image to Byte array OR WPF Image to byte[] OR https://github.com/teichgraf/WriteableBitmapEx/
Then you can simply throw any instance of this ImageDTO
to pretty much most Contract-based serialisers / deserialisers. For example, if you choose protocol-buffers, in .net land you can serialise with protobuf.net, while in javascript land you can deserialise with protobuf.js given the .proto
message ImageDTO {
optional int32 Width = 1 [default = 0];
optional int32 Height = 2 [default = 0];
optional ImageFormat Format = 3 [default = RGB];
optional bytes Data = 4;
optional string AltUrl = 5;
}
enum ImageFormat {
RGB = 0;
RGBA = 1;
PNG = 2;
JPEG = 3;
}
来源:https://stackoverflow.com/questions/35671829/datacontract-serialization-serialization-with-images