【问题标题】:How to serialize an object using it parents Interfaces?如何使用它的父接口序列化对象?
【发布时间】:2020-03-23 16:08:38
【问题描述】:

使用 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。 序列化包括所有接口属性的对象的最佳方法是什么?

【问题讨论】:

    标签: serialization .net-core interface json.net c#-8.0


    【解决方案1】:

    我最终创建了一个自定义合同解析器:

    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()));
    

    【讨论】:

      猜你喜欢
      • 2014-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多