我想实现一组类,可以与 UInt16 和 UInt32 类型参数一起使用。
第一个表示电报的标头,可以与 UInt32 和 UInt64 数据类型一起使用。
任何非必需字段已被省略!
public class Header<T> // where T : struct, IConvertible
{
public Header(T off, T len)
{
Offset = off;
LenData = len;
}
public T Offset;
public T LenData;
public byte[] ToByteArray()
{
byte[] bTemp = new byte[2 * Marshal.SizeOf(typeof(T))];
if (Offset is UInt16)
{
Array.ConstrainedCopy(System.BitConverter.GetBytes(Convert.ToUInt16(Offset)), 0, bTemp, 0, Marshal.SizeOf(typeof(T)));
Array.ConstrainedCopy(System.BitConverter.GetBytes(Convert.ToUInt16(LenData)), 0, bTemp, Marshal.SizeOf(typeof(T)), Marshal.SizeOf(typeof(T)));
}
else if (Offset is UInt32)
{
Array.ConstrainedCopy(System.BitConverter.GetBytes(Convert.ToUInt16(Offset)), 0, bTemp, 0, Marshal.SizeOf(typeof(T)));
Array.ConstrainedCopy(System.BitConverter.GetBytes(Convert.ToUInt16(LenData)), 0, bTemp, Marshal.SizeOf(typeof(T)), Marshal.SizeOf(typeof(T)));
}
else
{
throw new NotSupportedException("Type " + Offset.GetType() + "not supported");
}
return bTemp;
}
}
这个类为我提供了一个电报头的字节数组(T = UInt16 为 2 + 2 个字节,T = UInt32 为 4 + 4 个字节)。
现在我需要另一个类,它使用标头类来构建电报的字节数组:
class Telegram<T>
{
public Header<T> header;
public Telegram(T offset, byte[] bData)
{
header = new Header<T>(offset,bData.Length)
}
}
该类本身可以按预期工作:
static void Main(string[] args)
{
byte[] bData = new byte[16];
// This call works
Header<UInt16> ui16Header = new Header<ushort>(12345, (ushort)bData.Length);
byte[] b0 = ui16Header.ToByteArray();
b0 包含所需的电报内容...
然后我想创建两个电报(对于两种支持的数据类型:
// These calls don't work (because of compile error, or
// because of a thrown exception - see below)
Telegram<UInt16> telegram16 = new Telegram<ushort>(7000, bData);
Telegram<UInt32> telegram32 = new Telegram<uint>(70000, bData);
}
上面的类 Telegram 的构造函数无法编译(无法将 int 转换为 T)。
修改构造函数如下,即可编译:
public Telegram(T offset, byte[] bData)
{
object ot = bData.Length;
T len = (T)ot;
header = new Header<T>(offset, len);
}
但这会导致运行时异常。
这个问题能解决吗?我知道,我可以简单地编写两个包含所有类型特定方法本身的类,但只有标头中的字段是 UInt16 或 UInt32
或者这会是使用继承和接口的更简单的方法吗?
您可以使用新的
INumber
等界面。
这允许您与字节数组进行转换,以及与其他整数或数字类型进行转换。
public class Header<T> where T : struct, IBinaryInteger<T>
{
public Header(T off, T len)
{
Offset = off;
LenData = len;
}
public T Offset;
public T LenData;
public byte[] ToByteArray()
{
var size = Offset.GetByteCount();
byte[] bTemp = new byte[2 * size];
Offset.WriteLittleEndian(bTemp);
LenData.WriteLittleEndian(bTemp, size);
return bTemp;
}
}
public class Telegram<T> where T : struct, IBinaryInteger<T>
{
public Header<T> header;
public Telegram(T offset, byte[] bData)
{
header = new Header<T>(offset, T.CreateTruncating(bData.Length))
}
}