1

这似乎有效:

Model.Add(typeof(ScsMessage), true).AddSubType(20, typeof(Request));
Model.Add(typeof(ScsMessage), true).AddSubType(200, typeof(Event));

Model.Add(typeof(Request), true).AddSubType(102, typeof(Message));
Model.Add(typeof(Request), true).AddSubType(103, typeof(Like));
Model.Add(typeof(Request), true).AddSubType(104, typeof(Tag));

Model.Add(typeof(Event), true).AddSubType(202, typeof(UserEvent<Message>));
Model.Add(typeof(Event), true).AddSubType(203, typeof(UserEvent<Like>));
Model.Add(typeof(Event), true).AddSubType(204, typeof(UserEvent<Tag>));

其中 UserEvent 定义为:

public class UserEvent<T> :Event where T:Request

以下(尝试替换上面的第三段代码)似乎不起作用。它不会产生任何编译或运行时错误,但 UserEvent 的反序列化会产生奇怪的结果。

Model.Add(typeof(Event), true).AddSubType(201, typeof(UserEvent<Request>));

有没有办法做到这一点?每次我定义一个新类时,它都会节省样板代码。

谢谢

编辑:使用以下反射来设置。放在这里以防有人发现它有用。

        foreach (Type type in FindAllDerivedTypes<ScsMessage>
                      (Assembly.GetAssembly(typeof(Request))))
        {
            Model.Add(typeof(ScsMessage), true).AddSubType(counter++, type);
        }

        foreach (Type type in FindAllDerivedTypes<Request>
                       (Assembly.GetAssembly(typeof(Request))))
        {
            Model.Add(typeof(Request), true).AddSubType(counter++, type);
            Type constructed = typeof(UserEvent<>).MakeGenericType(type);
            Model.Add(typeof(Event), true).AddSubType(counter++, constructed);
        }

.

       public static List<Type> FindAllDerivedTypes<T>(Assembly assembly)
       {
        var derivedType = typeof(T);
        return assembly
            .GetTypes()
            .Where(t =>
                t != derivedType && t.BaseType == derivedType  &&
                derivedType.IsAssignableFrom(t)
                ).ToList();

        } 
4

1 回答 1

2

首先,关于您的反射示例,请注意- 密钥(数字)非常重要,您必须能够在将来可靠地重现此数字。我不希望您添加新的子类型并发现所有数据都失败,因为偏移量减少了一个。

无法重现问题;以下工作正常 - 请让我知道我缺少什么:

using ProtoBuf.Meta;
using System;
class UserEvent<T> :Event where T:Request
{
    public override string ToString()
    { // to show what we are working with
        return "UserEvent-of-" + typeof (T).Name;
    }
}

// infer the : Request here from the ^^^^
class Message : Request{}
class Like : Request { }
class Tag : Request { }

class ScsMessage {}
// infer : ScsMessage here from the 2 AddSubType
class Request : ScsMessage {}
class Event : ScsMessage { }

class Program
{

    static void Main()
    {
        var Model = TypeModel.Create();
        Model.Add(typeof(ScsMessage), true).AddSubType(20, typeof(Request));
        Model.Add(typeof(ScsMessage), true).AddSubType(200, typeof(Event));

        Model.Add(typeof(Request), true).AddSubType(102, typeof(Message));
        Model.Add(typeof(Request), true).AddSubType(103, typeof(Like));
        Model.Add(typeof(Request), true).AddSubType(104, typeof(Tag));

        Model.Add(typeof(Event), true).AddSubType(202, typeof(UserEvent<Message>));
        Model.Add(typeof(Event), true).AddSubType(203, typeof(UserEvent<Like>));
        Model.Add(typeof(Event), true).AddSubType(204, typeof(UserEvent<Tag>));

        var obj = new UserEvent<Like>();

        var clone = Model.DeepClone(obj);
        Console.WriteLine(obj);
        Console.WriteLine(clone);
    }
}
于 2012-04-28T20:17:31.750 回答