3

我正在编写一个具有一组协议缓冲区(使用 protobuf-net)的系统,我想在它们都继承的抽象类中定义这样的东西:

public byte[] GetBytes()

但是,protocol buffer serealiser 需要一个类型参数,有没有一些有效的方法来获取继承类的类型?

例子:

public byte[] GetBytes()
    {
        using (MemoryStream stream = new MemoryStream())
        {
            Serializer.Serialize<T /* what goes here? */>(stream, this);
            return stream.ToArray();
        }
    }
4

4 回答 4

4

直接写“T”吧?

然后在你的类声明中:

public class M<T>

?

- 编辑

然后当你继承它时:

public class Foo : M<Apple>
于 2009-08-17T00:08:27.903 回答
3

将您的基类定义为BaseClass<T>,然后您的派生类将 T 替换为序列化程序类型DerivedClass<SerializerType>

您还可以在类型参数上指定约束,例如

BaseClass<T> where T : SerializerBase

以下是您可以应用的约束类型的描述。

于 2009-08-17T00:10:56.230 回答
3

你可以通过反射来做到这一点,但 protobuf-net 为你做到了。

只需将您的电话更改为:

Serializer.NonGeneric.Serialize(stream, this /* Takes an object here */);

这通过在运行时通过反射构建通用方法来工作。有关详细信息,请检查代码(此处为第二种方法)。

于 2009-08-17T00:13:44.050 回答
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. 在反序列化期间,它将识别正确的派生(具体)类型并使用它,因此您也可以使用Deserializewith MyBase,它会根据原始数据的内容构造一个Fooor 。Bar

因此,以下内容基本相同:

Serializer.Serialize<BaseType>(dest, obj);
...
BaseType obj = Serializer.Deserialize<BaseType>(source);

Serializer.Serialize<DerivedType>(dest, obj);
...
DerivedType obj = Serializer.Deserialize<DerivedType>(source);

这里的主要区别是变量的类型。

于 2009-08-17T04:31:08.943 回答