我目前正在开发一个基于其他代码生成代码的项目。本质上将编程语言本身用作 DSL。
生成器目标之一是二进制 DataContract 序列化程序和为以下类生成的 ToBytes
[DataContract]
public partial class Root
{
[DataMember]
public int Number { get; set; }
[DataMember]
public Partial[] Partials { get; set; }
[DataMember]
public IList<ulong> Numbers { get; set; }
}
变成这样:
public int Size
{
get
{
var size = 8;
// Add size for collections and strings
size += Partials.Sum(entry => entry.Size);
size += Numbers.Count * 8;
return size;
}
}
public byte[] ToBytes()
{
var index = 0;
var bytes = new byte[Size];
return ToBytes(bytes, ref index);
}
public byte[] ToBytes(byte[] bytes, ref int index)
{
// Convert Number
Buffer.BlockCopy(BitConverter.GetBytes(Number), 0, bytes, index, 4);;
index += 4;
// Convert Partials
// Two bytes length information for each dimension
Buffer.BlockCopy(BitConverter.GetBytes((ushort)(Partials == null ? 0 : Partials.Length)), 0, bytes, index, 2);
index += 2;
foreach(var value in Partials ?? Enumerable.Empty<Partial>())
{
value.ToBytes(bytes, ref index);
}
// Convert Numbers
// Two bytes length information for each dimension
Buffer.BlockCopy(BitConverter.GetBytes((ushort)(Numbers == null ? 0 : Numbers.Count)), 0, bytes, index, 2);
index += 2;
foreach(var value in Numbers ?? Enumerable.Empty<ulong>())
{
Buffer.BlockCopy(BitConverter.GetBytes(value), 0, bytes, index, 8);;
index += 8;
}
return bytes;
}
现在即使很难,这真的很快,我正在寻找一种方法来加快Buffer.BlockCopy(BitConverter.GetBytes
. byte[]
为每次转换创建一个新的小块然后在我已经拥有byte[]
和位置时复制它似乎仍然是浪费资源。
任何想法如何最好地改进代码?
更新:基于@adrianm 评论,我将用 for 循环替换 foreach 数组并在 if 语句中包装可空类型。不需要像在另一个线程中那样使用结构。我宁愿使用类和 [DataContract] 属性。另外为了符合 Linux 规范,我不能使用 WinApi。
更新 2:添加了生成的代码的其余部分。感谢评论未来的版本将包括
if (index + Size > bytes.Length)
// Some error handling