C# 如何使用Protobuf Net序列化接口对象集合

C# 如何使用Protobuf Net序列化接口对象集合,c#,serialization,protobuf-net,C#,Serialization,Protobuf Net,我有以下类定义: [ProtoInclude(2, typeof(Foo))] public interface IFoo { double Bar { get; } } [ProtoContract] public class Foo : IFoo { [ProtoMember(1)] private double _bar { get { return Bar / 10; } set { Bar = 10 * value;

我有以下类定义:

[ProtoInclude(2, typeof(Foo))]
public interface IFoo
{
    double Bar { get; }
}



[ProtoContract]
public class Foo : IFoo
{
    [ProtoMember(1)]
    private double _bar
    {
        get { return Bar / 10; }
        set { Bar = 10 * value; }
    }

    public double Bar { get; private set; }
}



[ProtoContract]
public class MyClass
{
    [ProtoMember(1, OverwriteList = true)]
    public IReadOnlyList<IFoo> Foos { get; private set; }
}
[ProtoInclude(2,typeof(Foo))]
公共接口IFoo
{
双栏{get;}
}
[原始合同]
公共类Foo:IFoo
{
[原成员(1)]
私人双人酒吧
{
获取{返回条/10;}
设置{Bar=10*值;}
}
公共双栏{get;private set;}
}
[原始合同]
公共类MyClass
{
[原成员(1,OverwriteList=true)]
公共IReadOnlyList Foos{get;私有集;}
}
当我尝试使用protobuf net序列化MyClass对象时,我得到一个异常:System.InvalidOperationException:无法为:MyNamespace.MyClass准备序列化程序 ---->System.InvalidOperationException:没有为类型MyNamespace.IFoo定义序列化程序

在我的例子中,我知道存储在MyClass.Foos中的项的具体类型是Foo。我如何告诉protobuf在它看到IFoo类型的任何地方使用Foo类型?或者,如何使其包含Foo作为可用于在集合中实现IFoo的类之一

--编辑--

Sam的答案非常接近,因此它揭示了这种方法的另一个问题。就是说,。但是,有一个简单的解决方法,因为列表是在MyClass的构造函数中创建的。因此,MyClass可以更改为以下内容:

[ProtoContract]
public class MyClass
{
    [ProtoMember(1, OverwriteList = true)]
    private List<IFoo> MutableFoos { get; set; }

    public IReadOnlyList<IFoo> Foos
    {
        get { return MutableFoos; }
    }
}
[协议]
公共类MyClass
{
[原成员(1,OverwriteList=true)]
私有列表MutableFoos{get;set;}
公共IReadOnlyList Foos
{
获取{return MutableFoos;}
}
}

但是,MyClass的序列化仍然失败,消息为“System.InvalidOperationException:找不到代理项的合适的转换运算符:MyNamespace.IFoo/MyNamespace.Foo”。

在序列化成员中使用接口类的情况下,我始终无法执行此操作。相反,我最终不得不将混凝土类作为列表成员类型。以下是最终对我有效的方法:

[ProtoContract]
public class MyClass
{
    [ProtoMember(1, OverwriteList = true)]
    private List<Foo> MutableFoos { get; set; }

    public IReadOnlyList<IFoo> Foos
    {
        get { return MutableFoos; }
    }
}
[协议]
公共类MyClass
{
[原成员(1,OverwriteList=true)]
私有列表MutableFoos{get;set;}
公共IReadOnlyList Foos
{
获取{return MutableFoos;}
}
}

注意,序列化成员中的类型是
List
,而不是
List
。我从未想过如何让后者发挥作用。

Sam删除了他的答案(没有编译),但由于他的回答,我对我的问题进行了编辑,因此我觉得总结他的解决方案,为编辑提供上下文可能是有用的。本质上,他建议使用一个代理,通过调用
RuntimeTypeModel.Default.Add(typeof(IFoo),false)。setUrrogate(typeof(Foo))
在MyClass的静态构造函数中。我刚刚遇到了与代理InvalidOperationException相同的问题-你解决过吗?@kirbatious通常我会回答我自己的问题,如果我发现了什么,所以我的猜测是否定的。但是,在接下来的几天里,我将再次检查代码,看看我是否最终找到了实现这一点的方法。我会发布一个答案,或者在我确定后替换这个评论。@kirbatious不幸的是,我最终放弃了这个。因为我只有一个实现类型用于
IFoo
,所以我只是让私有序列化成员使用底层的具体类。我已经添加了一个答案,解释了在我的案例中这是如何工作的。但是,我认为,如果您使用列表中的每个成员序列化具体的类名(或者,如果您知道列表中的所有内容都具有相同的类型,则包含的类),则可以使用代理来执行类似的操作。不过我从来没有试过,我已经成功了。从您最初的问题和我能够实现的主要区别是,我在界面上放置了
ProtoContract
ProtoMember
。但我的实现相当复杂,使用的是接口,然后是泛型抽象类,然后是实现泛型抽象类的具体类。我用ProtoBuf装饰器装配接口,ProtoBuf装饰器包括具体类,并在适当的地方用ProtoMember装饰具体类。