首页 文章

将具有更多派生类型的通用对象分配/反序列化为具有较少派生类型的通用对象

提问于
浏览
1

我有一个具有以下结构的类

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 的详细信息

在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与'NewtonsoftPlayground.GenericEntity1 [[NewtonsoftPlayground.BaseClass,NewtonsoftPlayground,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]],NewtonsoftPlayground,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'不兼容 .

我怎样才能做到这一点?或者我不应该使用通用?如果是这样,我最终会在从队列中提取消息后到处编写类型转换,我试图避免这种情况 .

2 回答

  • 0

    我重新创建了以下代码:

    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,它将不负责序列化专门类所有的额外细节(我的意思是,你想序列化一个BaseClass,这正是你要序列化的) .

    将它们序列化为特定实例是您的工作:即如果您获得BaseClass并且您知道需要Derived1将该实例解析为Derived1,然后将其序列化 .

  • 1

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

    作为一种解决方法,我创建了一个静态方法,它基本上实例化 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;
        }
    

    我希望,这有助于某人 .

相关问题