ProtoContract打破了XmlMediaTypeFormatter行为

时间:2015-11-30 17:05:12

标签: c# protobuf-net xmlserializer

我有一个ASP.NET Web应用程序需要以JSON,XML和ProtoBuf的形式接受请求。为了让ProtoBuf工作,我需要使用[ProtoContract]注释DTO,但是一旦我这样做,XML就会停止工作。

我可以将问题与[ProtoContract]非常相似。我做了这个小测试应用程序:

class Program
{
    static void Main(string[] args)
    {
        var ser = new XmlMediaTypeFormatter();
        ser.UseXmlSerializer = true;
        Console.WriteLine($"With ProtoContract: {ser.CanReadType(typeof(Foo))}");
        Console.WriteLine($"Without ProtoContract: {ser.CanReadType(typeof(Foo1))}");
    }
}

[ProtoContract]
public class Foo
{
    [ProtoMember(0)]
    public string Bar { get; set; }
}

public class Foo1
{
    public string Bar1 { get; set; }
}

输出结果为:

With ProtoContract: False
Without ProtoContract: True

观察非常清楚,只要添加属性,XmlSerializer就不能再读取对象了。有人遇到过类似的行为吗?关于如何解决这个问题的任何想法?

1 个答案:

答案 0 :(得分:0)

这很有意思 - 我不知道它是怎么做的,但今天晚上我会看着反射器!

但是,在这种情况下修复很简单:

[ProtoMember(1)]
public string Bar { get; set; }

奇怪的是,我知道检查这一点的原因是0永远不是protobuf中的合法标签,但我非常感兴趣XmlMediaTypeFormatter 关心

更新:原因是因为XmlSerializer如何访问对象上的属性,但吞下异常意味着“不能,不能这样做”。它成为你实际问题的牺牲品;尝试:

new XmlSerializer(typeof(Foo));

您应该看到:

Unhandled Exception: System.InvalidOperationException: There was an error reflecting type 'Foo'. ---> System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: tag
   at ProtoBuf.ProtoMemberAttribute..ctor(Int32 tag) in c:\Dev\protobuf-net\protobuf-net\ProtoMemberAttribute.cs:line 47
   at System.Reflection.CustomAttribute._CreateCaObject(RuntimeModule pModule, IRuntimeMethodInfo pCtor, Byte** ppBlob, Byte* pEndBlob, Int32* pcNamedArgs)
   at System.Reflection.CustomAttribute.CreateCaObject(RuntimeModule module, IRuntimeMethodInfo ctor, IntPtr& blob, IntPtr blobEnd, Int32& namedArgs)
   at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, Int32 pcaCount, RuntimeType attributeFilterType, Boolean mustBeInheritable, IList derivedAttributes, Boolean isDecoratedTargetSecurityTransparent)

等等,只是ProtoMembmerAttribute抱怨非法标记。