serialization - 如何使用它的父接口序列化对象?
问题描述
使用 c# 8。我有一组具有默认实现的基本接口:
public interface IEventBase
{
string PostRoutingKey { get; set; }
string EventSource => Assembly.GetEntryAssembly()?.GetName().Name;
long Timestamp => DateTimeOffset.UtcNow.ToUnixTimeSeconds();
Guid EventId => Guid.NewGuid();
string EventKey { get; set; }
}
public interface IActionNotifiable : IEventBase
{
[JsonProperty(Required = Required.Always)]
string SenderName { get; set; }
[JsonProperty(Required = Required.Always)]
string ReceiverName { get; set; }
[JsonProperty(Required = Required.Always)]
string SenderId { get; set; }
[JsonProperty(Required = Required.Always)]
string ReceiverId { get; set; }
string Title { get; set; }
string ShortDescription { get; set; }
string LongDescription { get; set; }
ActionNotifiableStatusEnum Status { get; set; }
Dictionary<string, string> ExtraProperties { get; set; }
}
public interface IPush : IActionNotifiable
{
[JsonProperty(Required = Required.Always)]
public string CallbackUrl { get; set; }
}
public class DerivedConcretePush : IPush
{
public string PostRoutingKey { get; set; }= string.Empty;
public string EventKey { get; set; }= string.Empty;
public string SenderName { get; set; }= string.Empty;
public string ReceiverName { get; set; }= string.Empty;
public string SenderId { get; set; }= string.Empty;
public string ReceiverId { get; set; }= string.Empty;
public string Title { get; set; }= string.Empty;
public string ShortDescription { get; set; }= string.Empty;
public string LongDescription { get; set; }= string.Empty;
public ActionNotifiableStatusEnum Status { get; set; }
public Dictionary<string, string> ExtraProperties { get; set; } = new Dictionary<string, string>();
public string CallbackUrl { get; set; }= string.Empty;
}
并尝试使用来自https://www.newtonsoft.com/json的 SerilizeObject 序列化对象,执行以下操作:
var message = JsonConvert.SerializeObject(@event, JsonConvertExtension.GetCamelCaseSettings());
我的 JsonSettings 看起来像这样:
public static JsonSerializerSettings GetCamelCaseSettings()
{
return new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
NamingStrategy = new CamelCaseNamingStrategy()
},
Formatting = Formatting.Indented,
TypeNameHandling = TypeNameHandling.Auto
};
}
我得到这样的东西:
{
"postRoutingKey": "",
"eventKey": "sericy-rabbiteventconsumer-cli.DerivedConcretePush",
"senderName": "",
"receiverName": "",
"senderId": "",
"receiverId": "",
"title": "just a tittle",
"shortDescription": "",
"longDescription": "body",
"status": 0,
"extraProperties": {},
"callbackUrl": ""
}
我曾尝试使用TypeNameHandling
并将IEventBase
类型传递给SerializeObject
. 序列化包括所有接口属性的对象的最佳方法是什么?
解决方案
我最终创建了一个自定义合同解析器:
public class InterfaceContractResolver : DefaultContractResolver
{
private readonly Type[] _interfaceTypes;
private readonly ConcurrentDictionary<Type, Type> _typeToSerializeMap;
public InterfaceContractResolver(params Type[] interfaceTypes)
{
_interfaceTypes = interfaceTypes;
_typeToSerializeMap = new ConcurrentDictionary<Type, Type>();
NamingStrategy = new CamelCaseNamingStrategy();
}
protected override IList<JsonProperty> CreateProperties(
Type type,
MemberSerialization memberSerialization)
{
var typeToSerialize = _typeToSerializeMap.GetOrAdd(
type,
t => _interfaceTypes.FirstOrDefault(
it => it.IsAssignableFrom(t)) ?? t);
var props = base.CreateProperties(typeToSerialize, memberSerialization);
// mark all props as not ignored
foreach (var prop in props)
{
prop.Ignored = false;
}
return props;
}
}
internal static class JsonConvertExtension
{ {
public static JsonSerializerSettings GetCamelCaseSettings() public static JsonSerializerSettings SetupJsonSerializerSettings(Type eventType)
{ {
var eventTypes = eventType.GetParentTypes().ToArray();
return new JsonSerializerSettings return new JsonSerializerSettings
{ {
ContractResolver = new DefaultContractResolver ContractResolver = new InterfaceContractResolver(eventTypes),
{ Formatting = Formatting.Indented,
NamingStrategy = new CamelCaseNamingStrategy() TypeNameHandling = TypeNameHandling.Auto,
},
Formatting = Formatting.Indented
}; };
并使用以下类型调用它:
var message = JsonConvert.SerializeObject(@event, JsonConvertExtension.SetupJsonSerializerSettings(@event.GetType()));
推荐阅读
- orgchart - Orgchart JS 不能在智能手机上运行吗?
- node.js - 在 React Native 中安装 Realm 后,找不到模块 /../../node-pre-gyp
- ocaml - 如何使用参数运行 dune build @doc
- c# - 如果选择的项目与任何先前的选择(c#)相同,如何允许数组仅接受列表框的唯一索引并抛出异常?
- docker - docker中asp.net核心所需的Https
- angular - 角材料步进器更改图标颜色
- bigcommerce - 如何从 bigcommerce 中的订单产品详细信息中获取产品变体 ID?
- kotlin - 在 Corda 交易中需要特定方签名
- ios - UIPageViewController - 到下一个视图控制器的动画过渡与方向变化混合
- vue.js - Vue 2.6.0 - 如何使用新的插槽语法将插槽内容呈现到子组件的命名插槽