使用ServiceStack.Text反序列化派生泛型类型

时间:2017-03-28 16:38:28

标签: c# generics deserialization servicestack-text

我正在使用ServiceStack.Text来序列化/反序列化对象,然后将它们存储在Redis中,但是我遇到了一些不会按预期反序列化的对象。

我有一个基类型(遗留代码的位,许多项目使用此基类型),其属性类型为object。后来添加了基本类型的通用版本,将属性公开为泛型类型。

使用ServiceStack.Text序列化和反序列化泛型类型设置基类(类型对象)上的属性,而不是派生类上更具体的类型。

重现错误的简单控制台应用程序如下:

class Program
{
    public class Base<T> : Base
    {
        //hide the Value property on the base class
        public new T Value { get; set; }
    }

    public class Base
    {
        public object Value { get; set; }
    }

    static void Main(string[] args)
    {
        var a = new Base<List<string>>()
        {
            Value = new List<string>() { "one", "two", "three" },
        };

        var serialized = TypeSerializer.SerializeToString(a);
        var deserialized = TypeSerializer.DeserializeFromString<Base<List<string>>>(serialized);

        //throws a null ref exception
        Console.WriteLine(deserialized.Value.Count);
    }
}

在反序列化后设置断点,Visual Studio将base.Value显示为List&lt; string&gt;使用序列化列表的值,但是我的Base上的Value属性&lt; List&lt; String&gt;&gt; class为null。

Screenshot of debugger in Visual Studio

有没有办法配置TypeSerializer(或JsonSerializer)来正确设置更具体的属性而不是基类的属性?

感谢任何帮助。

<小时/> 的更新

基于答案,我通过使Base<T>Base继承自新的抽象基类来解决它,如下所示:

public abstract class DummyBase
{
    public string Test { get; set; } = "Test";
}

public class BaseResponse<T> : DummyBase
{
    public T Value { get; set; }
}

public class BaseResponse : DummyBase
{
    public object Value { get; set; }
}

1 个答案:

答案 0 :(得分:1)

即使Base.Value被隐藏,它仍然可以被反射看到(例如a.GetType().GetProperties()。这可能就是问题。

以下似乎有效。 Base<T>中的getter和setter只包装Base.Value。要使ServiceStack将字符串反序列化为正确的类型,必须DummyBase<T>

class Program
{
    public static void Main (string[] args)
    {
        var a = new Base<List<string>>()
        {
            Value = new List<string> { "one", "two", "three" },
        };

        var serialized = TypeSerializer.SerializeToString(a);
        var deserialized = TypeSerializer.DeserializeFromString<DummyBase<List<string>>>(serialized);

        // no longer throws a null ref exception
        Console.WriteLine(deserialized.Value.Count);
    }
}

public class DummyBase<T> 
{
    public T Value { get; set; }
}

public class Base<T> : Base
{ 
    public new T Value 
    {
        get { return (T)base.Value; }
        set { base.Value = value; }
    }
}

public class Base
{
    public object Value { get; set; }
}

当然,如果Base<T>没有从Base继承,则不需要这一切。