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.GenericEntity
1[[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;
}
我希望这对某人有所帮助。
我有一个 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.GenericEntity
1[[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.GenericEntity
1[[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;
}
我希望这对某人有所帮助。