我正在编写一个具有一组协议缓冲区的系统(使用protobuf-net),我想在它们都继承的抽象类中定义类似的东西:
public byte[] GetBytes()
但是,协议缓冲区serealiser需要一个类型参数,是否有一些有效的方法来获取继承类的类型?
示例:
public byte[] GetBytes()
{
using (MemoryStream stream = new MemoryStream())
{
Serializer.Serialize<T /* what goes here? */>(stream, this);
return stream.ToArray();
}
}
答案 0 :(得分:4)
只要写“T”吧?
然后在你的班级宣言中:
public class M<T>
- 编辑
然后当你继承它时:
public class Foo : M<Apple>
答案 1 :(得分:3)
将基类定义为BaseClass<T>
,然后派生类将T替换为序列化器类型DerivedClass<SerializerType>
。
您还可以在类型参数上指定约束,例如
BaseClass<T> where T : SerializerBase
Here描述了您可以应用的约束类型。
答案 2 :(得分:3)
你可以通过反思来做到这一点,但是protobuf-net为你做到了。
只需将您的电话改为:
即可Serializer.NonGeneric.Serialize(stream, this /* Takes an object here */);
这可以通过反射在运行时构建泛型方法。有关详细信息,请检查代码(second method here)。
答案 3 :(得分:1)
你实际上并不需要任何特别的东西......因为protobuf-net尊重继承。如果你有:
[ProtoInclude(typeof(Foo), 20)]
[ProtoInclude(typeof(Bar), 21)]
public abstract class MyBase {
/* other members */
public byte[] GetBytes()
{
using(MemoryStream ms = new MemoryStream())
{
Serializer.Serialize<MyBase>(ms, this); // MyBase can be implicit
return ms.ToArray();
}
}
}
[ProtoContract]
class Foo : MyBase { /* snip */ }
[ProtoContract]
class Bar : MyBase { /* snip */ }
然后它会起作用。要序列化数据,始终从基础(合同)类型开始;所以即使你做了Serializer.Serialize<Foo>(stream, obj)
,它首先会检测到它有一个合同的基类,然后切换到MyBase
。在反序列化期间,它将识别正确的派生(具体)类型并使用它,因此您也可以将Deserialize
与MyBase
一起使用,它将构建Foo
或Bar
取决于Serializer.Serialize<BaseType>(dest, obj);
...
BaseType obj = Serializer.Deserialize<BaseType>(source);
关于原始数据是什么。
因此以下内容基本相同:
Serializer.Serialize<DerivedType>(dest, obj);
...
DerivedType obj = Serializer.Deserialize<DerivedType>(source);
和
{{1}}
这里的主要区别在于如何输入变量。