Сериализация массива неизвестного типа с помощью Protobuf .Net - PullRequest
2 голосов
/ 20 февраля 2012

У меня возникло затруднение при попытке сериализации этой структуры данных:

protected string EngineQualifiedName
{
    get { return Engine == null ? null : Engine.AssemblyQualifiedName; }
    set { Engine = value == null? null : Type.GetType(value); }
}

public Type Engine { get; protected set; }

public string Method { get; protected set; }

public Type[] ParameterTypes { get; protected set; }

Проблема, очевидно, связана с сериализацией ParameterTypes. Читая о других подобных проблемах здесь в переполнении стека, я написал такой форматировщик:

public static IFormatter Formatter(IEnumerable<Type> paramTypes)
{
    RuntimeTypeModel.Default.Add(typeof(ProtoBufRequest), true).Add(1, "ParameterCompositeValues").Add(2, "EngineQualifiedName").Add(3, "Method");
    var ct = RuntimeTypeModel.Default.Add(typeof(CompositeType), true);         
    var ctType = typeof (CompositeType<>);

    var j = 0;
    foreach (var paramType in paramTypes)
    {
        try
        {
            RuntimeTypeModel.Default.Add(paramType, true);
        }
        catch
        { }

        ct.AddSubType(j + 4, ctType.MakeGenericType(paramType));

        j++;
    }

    return RuntimeTypeModel.Default.CreateFormatter(typeof (ProtoBufRequest));
}

И я использовал эти свойства и класс для маскировки массива типа:

private CompositeType[] ParameterCompositeValues
{
    get
    {
        if (ParameterValues == null)
            return null;

        var create = typeof (CompositeType).GetMethod("Create");
        return
            ParameterValues.Select(
                    (t, i) => (CompositeType) create.MakeGenericMethod(ParameterTypes[i]).Invoke(null, new[] {t})).ToArray();
    }
    set
    {
        ParameterValues = value == null ? null : value.Select(v => v.Value).ToArray();
    }
}

[ProtoContract(UseProtoMembersOnly = true)]
internal abstract class CompositeType
{
    protected abstract object ValueImpl { get; set; }

    public object Value
    {
        get { return ValueImpl; }
        set { ValueImpl = value; }
    }


    public static CompositeType<T> Create<T>(T value)
    {
        return new CompositeType<T> {Value = value};
    }
}


[ProtoContract(UseProtoMembersOnly = true)]
internal class CompositeType<T> : CompositeType
{
    [ProtoMember(1)]
    public new T Value { get; set; }

    protected override object ValueImpl
    {
        get { return Value; }
        set { Value = (T) value; }
    }
}

Моя проблема на самом деле заключается в том, что, когда я пытаюсь сериализовать классы обобщения (например, Speaker, где T не известен), форматировщик сталкивается с некоторыми проблемами, и при десериализации я получаю пустой класс со всеми его значениями ноль. Я делаю что-то неправильно? Универсальные классы корректно сериализуются, но если я попытаюсь настроить их таким образом, система сообщений не сможет правильно сериализоваться и десериализоваться: \

Буду признателен за любую помощь!

...