无法序列化泛型类型 [英] Can't serialize generic type

查看:123
本文介绍了无法序列化泛型类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用protobuf-net序列化一个泛型类型,但protobuf-net说它不能序列化它。



如:

  RuntimeTypeModel.Default.CanSerialize(typeof(MyGenericClass<>))

返回true并且

  RuntimeTypeModel.Default.CanSerialize(typeof(string ))

也会返回true。但是

  RuntimeTypeModel.Default.CanSerialize(typeof(MyGenericClass< string>))//  - >适用于所有直接序列化时返回true的类型,如上所示字符串类型

返回false。我想我在如何将 MyGenericClass 添加到默认运行时间类型模型中时出错。由于类似于

  RuntimeTypeModel.Default.CanSerialize(typeof(List< Document>))

返回true。



我添加泛型类的当前代码:

  var addedGenericType = RuntimeTypeModel.Default.Add(typeof(MyGenericClass<>),false); 
addedGenericType.Add(Field1,GenericField);

错误消息表明没有我试图序列化的类型的合约...这显然是不正确的。



下面是一个演示我的问题和证明它应该起作用的例子:

 使用System; 
使用ProtoBuf;

命名空间TestApplication
{
[ProtoContract]
public class TestClass< T>
{
[ProtoMember(1,DynamicType = true)]
public T TestField {get;组; }

}

public class TestClass2< T>
{
public T TestField {get;组; }
}

public class Tester
{
public void Test()
{
DefineSecondClass();
bool testResult = ProtoBuf.Meta.RuntimeTypeModel.Default.CanSerialize(typeof(TestClass< string>));
bool testResult2 = ProtoBuf.Meta.RuntimeTypeModel.Default.CanSerialize(typeof(TestClass2< string>));
bool testResult3 = ProtoBuf.Meta.RuntimeTypeModel.Default.CanSerialize(typeof(TestClass2<>));
Console.WriteLine(testResult); //返回true
Console.WriteLine(testResult2); //返回false
Console.WriteLine(testResult3); //返回true
}

private void DefineSecondClass()
{
var type = ProtoBuf.Meta.RuntimeTypeModel.Default.Add(typeof(TestClass2<> ),假);
type.AddField(1,TestField);
type [1] .DynamicType = true;


$ b $ / code>

作为后续(和澄清我的意见)让我们来看看这段代码:



using System;
使用ProtoBuf;

  namespace TestApplication 
{

public class TestClass< T>
{
public T TestField {get;组; }
}

public class ComplexType
{
public string SomeFieldA {get; set;}
public int SomeFieldB {get; set;}
}

public class Tester
{
public void Test()
{
DefineComplexType();
//如何添加类型TestClass< ComplexType>到RuntimeTypeModel而不调用
// DefineComplexType()呢?


private void DefineComplexType()
{
var type = ProtoBuf.Meta.RuntimeTypeModel.Default.Add(typeof(ComplexType),false);
type.AddField(1,SomeFieldA);




解决方案


  var type = ProtoBuf.Meta.RuntimeTypeModel.Default.Add(
typeof( TestClass2<>),false);
type.AddField(1,TestField);
type [1] .DynamicType = true;

您已将 TestClass2<> 类型。这很好,但是......你永远不会使用那种类型。事实上,它不能被使用 - Add 应该可能会引发错误。您可以使用 TestClass< string> ,这是完全独立的类型实例。



我猜这里的逻辑是:如果配置了泛型类型定义,则封闭泛型类型应该从泛型类型定义继承它的配置。我可以看到这一点的逻辑,但是:目前尚未实现,并且像其他任何事情一样,需要规范,设计,实施,测试,支持和文档。这需要时间。



今天:如果你想使用 TestClass2< string> ,你应该 configure TestClass2< string>



请注意,使用属性时,封闭类型;因此, TestClass1< string> .TestField 具有 [ProtoMember(1,DynamicType = true)] 标记。



我怀疑如果你这样做:

  private void DefineSecondClass()
{
var type = ProtoBuf.Meta.RuntimeTypeModel.Default.Add(
typeof(TestClass2< string>),false);
type.AddField(1,TestField);
type [1] .DynamicType = true;
}

那么它就会正常工作。


I'm trying to serialize a generic type with protobuf-net, but protobuf-net says it can't serialize it.

As in:

RuntimeTypeModel.Default.CanSerialize(typeof(MyGenericClass<>))

returns true and

RuntimeTypeModel.Default.CanSerialize(typeof(string))

returns true, too. But

RuntimeTypeModel.Default.CanSerialize(typeof(MyGenericClass<string>)) //--> applies to all types that would return true when directly serialized as shown above for the string type

returns false. I guess I'm doing something wrong with how I add my MyGenericClass to the default runtimetype model. Since something like

RuntimeTypeModel.Default.CanSerialize(typeof(List<Document>))

returns true.

My current code for adding the generic class:

var addedGenericType = RuntimeTypeModel.Default.Add(typeof(MyGenericClass<>), false);
addedGenericType.Add("Field1", "GenericField");

The error message says that there is no contract for the type I'm trying to serialize...which is obviously not true.

Here is an example demonstrating my problem and proofing that it should work:

using System;
using ProtoBuf;

namespace TestApplication
{
    [ProtoContract]
    public class TestClass<T>
    {
        [ProtoMember(1, DynamicType = true)]
        public T TestField { get; set; }

    }

    public class TestClass2<T>
    {
        public T TestField { get; set; }
    }

    public class Tester
    {
        public void Test()
        {
            DefineSecondClass();
            bool testResult = ProtoBuf.Meta.RuntimeTypeModel.Default.CanSerialize(typeof(TestClass<string>));            
            bool testResult2 = ProtoBuf.Meta.RuntimeTypeModel.Default.CanSerialize(typeof(TestClass2<string>));
            bool testResult3 = ProtoBuf.Meta.RuntimeTypeModel.Default.CanSerialize(typeof(TestClass2<>));
            Console.WriteLine(testResult); // returns true
            Console.WriteLine(testResult2); // returns false
            Console.WriteLine(testResult3); // returns true
        }

        private void DefineSecondClass()
        {
            var type = ProtoBuf.Meta.RuntimeTypeModel.Default.Add(typeof(TestClass2<>), false);
            type.AddField(1, "TestField");
            type[1].DynamicType = true;
        }
    }
}

As a follow up (and to clarify my comments) let's take this code:

using System; using ProtoBuf;

namespace TestApplication
{        

    public class TestClass<T>
    {
        public T TestField { get; set; }
    }

    public class ComplexType
    {
        public string SomeFieldA{get; set;}
        public int SomeFieldB{get; set;}
    }

    public class Tester
    {
        public void Test()
        {
            DefineComplexType();
            // how to add the type TestClass<ComplexType> to the RuntimeTypeModel without calling
            // DefineComplexType() again?
        }

        private void DefineComplexType()
        {
            var type = ProtoBuf.Meta.RuntimeTypeModel.Default.Add(typeof(ComplexType), false);
            type.AddField(1, "SomeFieldA");
        }
    }
}

解决方案

By doing:

var type = ProtoBuf.Meta.RuntimeTypeModel.Default.Add(
    typeof(TestClass2<>), false);
type.AddField(1, "TestField");
type[1].DynamicType = true;

You have configured the TestClass2<> type. Which is great, but... you never use that type. In fact, it cannot be used - Add should probably throw an error. You use TestClass<string> which to most intents and purposes is a completely separate Type instance.

I guess the logic here is that: a closed generic type should inherit its configuration from the generic type definition, if the generic type definition is configured. I can see the logic of that, but: that is not currently implemented, and like everything else would require specification, design, implementation, testing, support and documentation. Which takes time.

For today: if you want to work with TestClass2<string>, you should configure TestClass2<string>.

Note that when using attributes, attributes are inherently present on the closed types; so it is the case that TestClass1<string>.TestField has the [ProtoMember(1, DynamicType = true)] marker.

I suspect that if you do:

private void DefineSecondClass()
{
    var type = ProtoBuf.Meta.RuntimeTypeModel.Default.Add(
        typeof(TestClass2<string>), false);
    type.AddField(1, "TestField");
    type[1].DynamicType = true;
}

then it will work fine.

这篇关于无法序列化泛型类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆