Assign/Deserialize 派生类型较多的泛型对象转换为派生类型较少的泛型对象

Assign/Deserialize generic object with more derived type into the one with less derived type

我有一个 class 具有以下结构

public class GenericEntity<T>
    where T : BaseClass
{
    T Property {get; set;}
}

我有几个 BaseClass 的具体实现,我正在使用这些具体实现来实例化 GenericEntity

类型的对象

例如var entity = new GenericEntity<DerivedClass>()

我通过将对象序列化为 JSON(使用 Newtonsoft)将此实体推送到消息传递框架中。在另一端,我正在从消息队列中提取该消息 (JSON),并尝试使用 JsonSerializerSettings TypeNameHandling.All 将消息反序列化为类型 GenericEntity<BaseClass>。但是在反序列化的时候,它会抛出 JsonSerializationException with details

Type specified in JSON 'NewtonsoftPlayground.GenericEntity1[[NewtonsoftPlayground.DerivedClass, NewtonsoftPlayground, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], NewtonsoftPlayground, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not compatible with 'NewtonsoftPlayground.GenericEntity1[[NewtonsoftPlayground.BaseClass, NewtonsoftPlayground, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], NewtonsoftPlayground, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

我怎样才能做到这一点?还是我不应该使用泛型?如果是这样,我最终会在从队列中提取消息后到处写类型转换,这是我试图避免的。

我重新创建了以下代码:

public class GenericEntity<T> where T : BaseClass 
    {
   public T Property { get; set; }
}

public class BaseClass {
}

class Derived1 : BaseClass
{
    public int Age { get; set; }
}

class Derived2 : BaseClass {
    public string Name { get; set; }
}

....

static void Main()
    {
        Derived1 d1 = new Derived1 {Age = 23};
        GenericEntity<Derived1> entity = new GenericEntity<Derived1> {Property = d1};

        var data = JsonConvert.SerializeObject(entity, new JsonSerializerSettings() {
            TypeNameHandling = TypeNameHandling.All
        });
        var baseEntity = JsonConvert.DeserializeObject(data, typeof(GenericEntity<BaseClass>));
}

我在反序列化数据时没有遇到任何错误。让我知道您的背景以及它有何不同。

这显然行不通:

        BaseClass d1 = new Derived1 {Age = 23};
        GenericEntity<BaseClass> entity = new GenericEntity<BaseClass> {Property = d1};

        var data = JsonConvert.SerializeObject(entity, new JsonSerializerSettings() {
            TypeNameHandling = TypeNameHandling.All
        });
        var baseEntity = JsonConvert.DeserializeObject<GenericEntity<Derived1>>(data, new JsonSerializerSettings()
        {
            TypeNameHandling = TypeNameHandling.All
        });

如果您序列化一个 BaseClass,它不会负责序列化专用 class 具有的所有额外细节(我的意思是,您想要序列化一个 BaseClass,而这正是您要序列化的) .

将它们序列化为专用实例是您的工作:也就是说,如果您获得一个 BaseClass 并且您知道您需要一个 Derived1 将该实例解析为 Derived1,然后将其序列化。

我找不到任何直接的解决方案来实现这一点。正如@Tamas Ionut 建议的那样,在反序列化时指定基数 class 不会反序列化具体 class.

的属性

作为解决方法,我创建了一个静态方法,它基本上实例化 GenericEntity<BaseClass> 并使用反射复制其中的所有属性。

    public static GenericEntity<BaseClass> ConvertToBaseEntity(object model)
    {
        if (model.GetType().GetGenericTypeDefinition() != typeof(GenericEntity<>))
        {
            throw new ArgumentException(
                "Model should be of type GenericEntity<T>.", "model");
        }

        GenericEntity<BaseClass> baseModel = new GenericEntity<BaseClass>();

        foreach (var propertyInfo in model.GetType().GetProperties())
        {
            baseModel.GetType().GetProperty(propertyInfo.Name).SetValue(baseModel, propertyInfo.GetValue(model));
        }

        return baseModel;
    }

我希望这对某人有所帮助。