C# 序列化XAML的ConcurrentBag
我的代码中有一个C# 序列化XAML的ConcurrentBag,c#,.net,wpf,xaml,concurrency,C#,.net,Wpf,Xaml,Concurrency,我的代码中有一个ConcurrentBag 我想知道如何序列化它们。当然,我可以迭代或使用提供者模型类打包它,但我想知道是否已经完成了 Point3DCollections本身可能相当大,可以进行压缩以加快磁盘的读写速度,但我需要的响应时间主要取决于用户界面规模。换句话说,出于性能原因,我更喜欢二进制格式,而不是XAML文本格式。(有一个很好的XAML文本序列化程序,它是Helix 3D CodeProject的一部分,但是它比我想要的慢。) 这是一个让我推出自己的序列化程序的用例,还是已经为这
ConcurrentBag
我想知道如何序列化它们。当然,我可以迭代或使用提供者模型类打包它,但我想知道是否已经完成了
Point3DCollection
s本身可能相当大,可以进行压缩以加快磁盘的读写速度,但我需要的响应时间主要取决于用户界面规模。换句话说,出于性能原因,我更喜欢二进制格式,而不是XAML文本格式。(有一个很好的XAML文本序列化程序,它是Helix 3D CodeProject的一部分,但是它比我想要的慢。)
这是一个让我推出自己的序列化程序的用例,还是已经为这种数据打包了一些东西 压缩可能会利用重复坐标。序列化程序通常也会对重复对象使用引用,尽管我不确定是否有很多设置可以使用结构(如Point3D)。无论如何,这里有一些如何序列化的例子。要使用标准格式化程序,需要将数据类型转换为大多数格式化程序支持的类型:列表/数组。下面的代码使用Nuget包NUnit和Json.NET
using Newtonsoft.Json;
using Newtonsoft.Json.Bson;
using NUnit.Framework;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Windows.Media.Media3D;
namespace DemoPoint3DSerialize
{
[TestFixture]
class Tests
{
[Test]
public void DemoBinary()
{
// this shows how to convert them all to strings
var collection = CreateCollection();
var data = collection.Select(c => c.ToArray()).ToList(); // switch to serializable types
var formatter = new BinaryFormatter();
using (var ms = new MemoryStream())
{
formatter.Serialize(ms, data);
Trace.WriteLine("Binary of Array Size: " + ms.Position);
ms.Position = 0;
var dupe = (List<Point3D[]>)formatter.Deserialize(ms);
var result = new ConcurrentBag<Point3DCollection>(dupe.Select(r => new Point3DCollection(r)));
VerifyEquality(collection, result);
}
}
[Test]
public void DemoString()
{
// this shows how to convert them all to strings
var collection = CreateCollection();
IEnumerable<IList<Point3D>> tmp = collection;
var strings = collection.Select(c => c.ToString()).ToList();
Trace.WriteLine("String Size: " + strings.Sum(s => s.Length)); // eh, 2x for Unicode
var result = new ConcurrentBag<Point3DCollection>(strings.Select(r => Point3DCollection.Parse(r)));
VerifyEquality(collection, result);
}
[Test]
public void DemoDeflateString()
{
// this shows how to convert them all to strings
var collection = CreateCollection();
var formatter = new BinaryFormatter(); // not really helping much: could
var strings = collection.Select(c => c.ToString()).ToList();
using (var ms = new MemoryStream())
{
using (var def = new DeflateStream(ms, CompressionLevel.Optimal, true))
{
formatter.Serialize(def, strings);
}
Trace.WriteLine("Deflate Size: " + ms.Position);
ms.Position = 0;
using (var def = new DeflateStream(ms, CompressionMode.Decompress))
{
var stringsDupe = (IList<string>)formatter.Deserialize(def);
var result = new ConcurrentBag<Point3DCollection>(stringsDupe.Select(r => Point3DCollection.Parse(r)));
VerifyEquality(collection, result);
}
}
}
[Test]
public void DemoStraightJson()
{
// this uses Json.NET
var collection = CreateCollection();
var formatter = new JsonSerializer();
using (var ms = new MemoryStream())
{
using (var stream = new StreamWriter(ms, new UTF8Encoding(true), 2048, true))
using (var writer = new JsonTextWriter(stream))
{
formatter.Serialize(writer, collection);
}
Trace.WriteLine("JSON Size: " + ms.Position);
ms.Position = 0;
using (var stream = new StreamReader(ms))
using (var reader = new JsonTextReader(stream))
{
var result = formatter.Deserialize<List<Point3DCollection>>(reader);
VerifyEquality(collection, new ConcurrentBag<Point3DCollection>(result));
}
}
}
[Test]
public void DemoBsonOfArray()
{
// this uses Json.NET
var collection = CreateCollection();
var formatter = new JsonSerializer();
using (var ms = new MemoryStream())
{
using (var stream = new BinaryWriter(ms, new UTF8Encoding(true), true))
using (var writer = new BsonWriter(stream))
{
formatter.Serialize(writer, collection);
}
Trace.WriteLine("BSON Size: " + ms.Position);
ms.Position = 0;
using (var stream = new BinaryReader(ms))
using (var reader = new BsonReader(stream, true, DateTimeKind.Unspecified))
{
var result = formatter.Deserialize<List<Point3DCollection>>(reader); // doesn't seem to read out that concurrentBag
VerifyEquality(collection, new ConcurrentBag<Point3DCollection>(result));
}
}
}
private ConcurrentBag<Point3DCollection> CreateCollection()
{
var rand = new Random(42);
var bag = new ConcurrentBag<Point3DCollection>();
for (int i = 0; i < 10; i++)
{
var collection = new Point3DCollection();
for (int j = 0; j < i + 10; j++)
{
var point = new Point3D(rand.NextDouble(), rand.NextDouble(), rand.NextDouble());
collection.Add(point);
}
bag.Add(collection);
}
return bag;
}
private class CollectionComparer : IEqualityComparer<Point3DCollection>
{
public bool Equals(Point3DCollection x, Point3DCollection y)
{
return x.SequenceEqual(y);
}
public int GetHashCode(Point3DCollection obj)
{
return obj.GetHashCode();
}
}
private void VerifyEquality(ConcurrentBag<Point3DCollection> collection, ConcurrentBag<Point3DCollection> result)
{
var first = collection.OrderBy(c => c.Count);
var second = collection.OrderBy(c => c.Count);
first.SequenceEqual(second, new CollectionComparer());
}
}
}
使用Newtonsoft.Json;
使用Newtonsoft.Json.Bson;
使用NUnit.Framework;
使用制度;
使用System.Collections.Concurrent;
使用System.Collections.Generic;
使用系统诊断;
使用System.IO;
使用系统IO压缩;
使用System.Linq;
使用System.Runtime.Serialization.Formatters.Binary;
使用系统文本;
使用System.Windows.Media.Media3D;
命名空间DemoPoint3DSerialize
{
[测试夹具]
课堂测试
{
[测试]
public void DemoBinary()
{
//这显示了如何将它们全部转换为字符串
var collection=CreateCollection();
var data=collection.Select(c=>c.ToArray()).ToList();//切换到可序列化类型
var formatter=新的二进制格式化程序();
使用(var ms=new MemoryStream())
{
格式化程序。序列化(ms、数据);
Trace.WriteLine(“数组大小的二进制:“+ms.Position”);
ms.Position=0;
var dupe=(列表)格式化程序。反序列化(ms);
var结果=新的ConcurrentBag(复制选择(r=>NewPoint3DCollection(r));
验证相等性(收集、结果);
}
}
[测试]
公共字符串()
{
//这显示了如何将它们全部转换为字符串
var collection=CreateCollection();
IEnumerable tmp=集合;
var strings=collection.Select(c=>c.ToString()).ToList();
Trace.WriteLine(“字符串大小:”+strings.Sum(s=>s.Length));//呃,Unicode为2x
var result=newconcurrentbag(strings.Select(r=>Point3DCollection.Parse(r));
验证相等性(收集、结果);
}
[测试]
public void DemoDeflateString()
{
//这显示了如何将它们全部转换为字符串
var collection=CreateCollection();
var formatter=new BinaryFormatter();//实际上帮助不大:可以
var strings=collection.Select(c=>c.ToString()).ToList();
使用(var ms=new MemoryStream())
{
使用(var def=新的DeflateStream(毫秒,压缩级别。最佳,真))
{
序列化(定义,字符串);
}
Trace.WriteLine(“放气大小:+ms.Position”);
ms.Position=0;
使用(var def=新的放气流(ms,压缩模式。解压缩))
{
var stringsDupe=(IList)格式化程序。反序列化(def);
var result=newconcurrentbag(stringsDupe.Select(r=>Point3DCollection.Parse(r));
验证相等性(收集、结果);
}
}
}
[测试]
public-void-json()
{
//它使用Json.NET
var collection=CreateCollection();
var formatter=new JsonSerializer();
使用(var ms=new MemoryStream())
{
使用(var stream=newstreamwriter(ms,新的UTF8Encoding(true),2048,true))
使用(var writer=newjsontextwriter(流))
{
序列化(编写器、集合);
}
Trace.WriteLine(“JSON大小:+ms.Position”);
ms.Position=0;
使用(var stream=新的StreamReader(ms))
使用(var reader=newjsontextreader(流))
{
var result=格式化程序。反序列化(读取器);
验证相等性(收集、新ConcurrentBag(结果));
}
}
}
[测试]
公共void DemoBsonOfArray()
{
//它使用Json.NET
var collection=CreateCollection();
var formatter=new JsonSerializer();
使用(var ms=new MemoryStream())
{
使用(var stream=newbinarywriter(ms,newutf8encoding(true),true))
使用(var writer=newbsonwriter(流))
{
序列化(编写器、集合);
}
Trace.WriteLine(“BSON大小:+ms.Position”);
ms.Position=0;
使用(var流=新二进制读取器(ms))
使用(var reader=newbsonreader(stream,true,DateTimeKind.Unspecified))
{
var result=formatter.Deserialize(reader);//似乎没有读取concurrentBag
验证平等性(收集,新ConcurrentBag(r
public static class Point3DExtensions
{
public static void StringSerialize(this ConcurrentBag<Point3DCollection> bag, Stream stream)
{
if (bag == null)
throw new ArgumentNullException("bag");
if (stream == null)
throw new ArgumentNullException("stream");
StreamWriter writer = new StreamWriter(stream);
Point3DCollectionConverter converter = new Point3DCollectionConverter();
foreach (Point3DCollection coll in bag)
{
// we need to use the english locale as the converter needs that for parsing...
string line = (string)converter.ConvertTo(null, CultureInfo.GetCultureInfo("en-US"), coll, typeof(string));
writer.WriteLine(line);
}
writer.Flush();
}
public static void StringDeserialize(this ConcurrentBag<Point3DCollection> bag, Stream stream)
{
if (bag == null)
throw new ArgumentNullException("bag");
if (stream == null)
throw new ArgumentNullException("stream");
StreamReader reader = new StreamReader(stream);
Point3DCollectionConverter converter = new Point3DCollectionConverter();
do
{
string line = reader.ReadLine();
if (line == null)
break;
bag.Add((Point3DCollection)converter.ConvertFrom(line));
// NOTE: could also use this:
//bag.Add(Point3DCollection.Parse(line));
}
while (true);
}
public static void BinarySerialize(this ConcurrentBag<Point3DCollection> bag, Stream stream)
{
if (bag == null)
throw new ArgumentNullException("bag");
if (stream == null)
throw new ArgumentNullException("stream");
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(bag.Count);
foreach (Point3DCollection coll in bag)
{
writer.Write(coll.Count);
foreach (Point3D point in coll)
{
writer.Write(point.X);
writer.Write(point.Y);
writer.Write(point.Z);
}
}
writer.Flush();
}
public static void BinaryDeserialize(this ConcurrentBag<Point3DCollection> bag, Stream stream)
{
if (bag == null)
throw new ArgumentNullException("bag");
if (stream == null)
throw new ArgumentNullException("stream");
BinaryReader reader = new BinaryReader(stream);
int count = reader.ReadInt32();
for (int i = 0; i < count; i++)
{
int pointCount = reader.ReadInt32();
Point3DCollection coll = new Point3DCollection(pointCount);
for (int j = 0; j < pointCount; j++)
{
coll.Add(new Point3D(reader.ReadDouble(), reader.ReadDouble(), reader.ReadDouble()));
}
bag.Add(coll);
}
}
}
static void Main(string[] args)
{
Random rand = new Random(Environment.TickCount);
ConcurrentBag<Point3DCollection> bag = new ConcurrentBag<Point3DCollection>();
for (int i = 0; i < 100; i++)
{
Point3DCollection coll = new Point3DCollection();
bag.Add(coll);
for (int j = rand.Next(10); j < rand.Next(100); j++)
{
Point3D point = new Point3D(rand.NextDouble(), rand.NextDouble(), rand.NextDouble());
coll.Add(point);
}
}
using (FileStream stream = new FileStream("test.bin", FileMode.Create))
{
bag.StringSerialize(stream); // or Binary
}
ConcurrentBag<Point3DCollection> newbag = new ConcurrentBag<Point3DCollection>();
using (FileStream stream = new FileStream("test.bin", FileMode.Open))
{
newbag.StringDeserialize(stream); // or Binary
foreach (Point3DCollection coll in newbag)
{
foreach (Point3D point in coll)
{
Console.WriteLine(point);
}
Console.WriteLine();
}
}
}
}
[ProtoContract]
public class MyClass {
public ConcurrentQueue<Point3DCollection> Points {get;set;}
[ProtoMember(1)]
private Point3DCollection[] Items
{
get { return Points.ToArray(); }
set { Items = new ConcurrentBag<Point3DCollection>(value); }
}
}