【问题标题】:protobuf-net: Cannot Serialize using System.Enum propertyprotobuf-net:无法使用 System.Enum 属性进行序列化
【发布时间】:2021-09-21 18:06:25
【问题描述】:

我会试着用一个例子来解释我想要做什么

[ProtoContract]
[ProtoInclude(101, typeof(SomeDerived))]
[ProtoInclude(102, typeof(AnotherDerived))]
public abstract class Base
{
    protected Base() {}
    public Base(double doubleProp, Enum enumProp)
    {
        DoubleProp = doubleProp;
        EnumProp = enumProp;
    }
    [ProtoMember(1)]
    public double DoubleProp { get; }
    [ProtoMember(2)]
    public Enum EnumProp { get; }
    
    //More stuff

}

public enum SomeDerivedEnum
{
    //Some Enum Values
}

public enum AnotherDerivedEnum
{
    //Another Enum Values
}

public class SomeDerived : Base
{
    private SomeDerived () : base() {}
    
    public SomeDerived (double doubleProp, SomeDerivedEnum someEnum)
        : base(doubleProp, someEnum)
    {
    }

    //More Stuff

}

public class AnotherDerived : Base
{
    private AnotherDerived () : base() {}
    
    public AnotherDerived (double doubleProp, AnotherDerivedEnum anotherEnum)
        : base(doubleProp, anotherEnum)
    {
    }

    //More Stuff

}

当我尝试序列化时,出现以下错误

System.InvalidOperationException:没有为类型定义序列化程序:System.Enum

有一种方法可以将任何 System.Enum 值转换为 int 并返回 protobuf?

【问题讨论】:

  • Enum 类型是所有枚举类型的基本类型,但它本身不是枚举类型。并非所有枚举类型都由int 支持——这是默认设置,但拥有MyEnum : long 会产生一个可能无法序列化为int 的枚举类型。因为枚举值的实际托管类型不是枚举值的一部分,所以如果它只有Enum,protobuf 就不可能将任意值反序列化为“正确的”枚举类型。总之,如果要int序列化,使用int;稍后根据需要转换为枚举(例如,通过单独的属性)。
  • 正如@Jeroen 所说:使用特定的枚举类型,而不是基本类型

标签: c# enums protobuf-net


【解决方案1】:

感谢cmets!我根据我读过的其他一些帖子找到了一种方法。

响应第一个 cmets,我无法在基类上定义特定的枚举,因为我事先不知道,每个派生类都有自己的枚举。所以我想出了一个不同的方法。

首先我添加了一个函数:

在基地:

protected virtual Type GetEnumtype() => typeof(Enum) 

在 SomeDerived 上(例如)

 protected override Type GetEnumType() => typeof(SomeDeviredEnum);

然后我创建了一个中间私有 int 属性来序列化我的枚举并使用覆盖函数进行转换。

[ProtoMember(2)]
private int intPvtProp 
{ 
    get => System.Convert.ToInt32(EnumProp); 
    set => EnumProp = (Enum)Enum.ToObject(GetEnumType(), value); 
}

public Enum EnumProp { get; }

我真的不知道是否是最好的方法,但它确实有效!

【讨论】:

  • EnumProp 似乎几乎没有任何价值,因为客户端在不知道类型的情况下无法有意义地使用它(从功能上讲,它与将 EnumProp 声明为 object 几乎没有区别)。鉴于这种情况,您不妨保留int,并使使用EnumProp 的任何代码现在负责转换,而不是此属性。
  • 或者,从基础中删除EnumProp,给它一个protected int,并让每个类以强类型的方式简单地使用它自己的枚举类型(public DerivedEnum EnumProp { get => (DerivedEnum) BaseInt; set => BaseInt = (int) value; })。这意味着不同类的EnumProps 之间没有关系,但枚举之间的“继承”概念一开始就令人怀疑(没有什么可以强制执行子集关系)。同样,以与类型无关的方式访问枚举意味着强制转换objectdynamic,没有一个比int 更方便。
猜你喜欢
  • 2017-03-09
  • 2013-02-03
  • 1970-01-01
  • 1970-01-01
  • 2013-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-26
相关资源
最近更新 更多