Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
964 views
in Technique[技术] by (71.8m points)

c# - Protobuf attributes with a hierarchy of generic classes

I have a class hierarchy that looks like this. These classes contain a lot of other details which I have excluded. This is a simplification to focus on the serialization aspect of these classes.

[ProtoInclude(1, typeof(Query<bool>))]
[ProtoInclude(2, typeof(Query<string>))]
[ProtoInclude(3, typeof(Query<int>))]
[ProtoInclude(4, typeof(Query<decimal>))]
[ProtoInclude(5, typeof(Query<DataSet>))]
abstract class Query
{
    public string Result { get; set; }
}
[ProtoInclude(1, typeof(SpecialQuery)]
abstract class Query<T> : Query
{
    public new T Result { get; set; }
}
abstract class SpecialQuery : Query<DataSet>
{
    public new string Result { get; set; }
}

I also have about 150 auto-generated descendants of generic Query, with a large variety of generic types. For example:

[ProtoContract]
class W : Query<bool>
{
}
[ProtoContract]
class X : Query<string>
{
}
[ProtoContract]
class Y : Query<int>
{
}
[ProtoContract]
class Z : SpecialQuery
{
}

I've also autogenerated [ProtoInclude] for all those types. For example:

[ProtoInclude(1, typeof(W)]
[ProtoInclude(2, typeof(X)]
[ProtoInclude(3, typeof(Y)]
[ProtoInclude(4, typeof(Z)]

The question is, how do I deploy those 150 ProtoIncludes? I've tried various combinations that seem logical, but I get various exceptions depending on which attributes are present where. The types that are actually need serialization in the above example would be W, X, Y, Z, only there's about 150 of them.

Can protobuf-net even deal with something like this, or should I try some other kind of serialization?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I'm not 100% sure I understand the scenario you want to model; however, [ProtoInclude] only looks one level of inheritance away.

If I understand correctly, try the following; note that you would need to know the potential generic types at compile time at the moment:

using System;
using ProtoBuf;
[ProtoContract]
[ProtoInclude(2, typeof(Response))]
[ProtoInclude(3, typeof(Query))]
class Packet
{
    [ProtoMember(1)]
    int ID;
}
[ProtoContract]
[ProtoInclude(1, typeof(Response<int>))]
[ProtoInclude(2, typeof(Response<decimal>))]
[ProtoInclude(3, typeof(Response<string>))]
class Response : Packet
{
}
[ProtoContract]
class Response<T> : Response
{
    [ProtoMember(2)]
    public T Value;

    public override string ToString()
    {
        return typeof(T).Name + ": " + Value;
    }
}
static class Program
{
    static void Main()
    {
        Packet packet = new Response<int> { Value = 123 };
        Packet clone = Serializer.DeepClone<Packet>(packet);
        Console.WriteLine(clone.ToString()); // should be int/123
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...