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

次の(上記のコードの3番目の段落を置き換えようとする)は機能しないようです。コンパイルエラーや実行時エラーは発生しませんが、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

まず、リフレクションの例に関して注意してください。キー (数字) は非常に重要であり、将来この数字を確実に再現できる必要があります。新しいサブタイプを追加して、オフセットが1つずれているためにすべてのデータが失敗することを望んでいません。

問題を再現できません。以下は正常に動作します - 私が欠けているものを教えてください:

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 に答える