我需要序列化/反序列化从一个或几个基本接口/抽象类派生的不同对象的列表。
这是我的模特:
public abstract class PaymentLogBase : IPaymentLog
{
public StatisticsPaymentType Type { get; }
public PaymentLogBase(StatisticsPaymentType type)
{
Type = type;
}
}
public abstract class NumberedLog : PaymentLogBase
{
public NumberedLog(StatisticsPaymentType type)
: base(type)
{
}
public string Number { get; set; }
}
public abstract class CardLog : NumberedLog
{
public CardLog(StatisticsPaymentType type)
: base(type)
{
}
public string CardInfo { get; set; }
}
public abstract class CreditCardLog : CardLog
{
public CreditCardLog(StatisticsPaymentType type)
: base(type)
{
}
public string Stan { get; set; }
}
public class CreditCardContactLessLog : CreditCardLog
{
public CreditCardContactLessLog()
: base(StatisticsPaymentType.ContactLessCc)
{
}
}
public class CreditCardContactLog : CreditCardLog
{
public CreditCardContactLog()
: base(StatisticsPaymentType.ContactCc)
{
}
}
public class UnsupportedCardLog : CardLog
{
public UnsupportedCardLog()
: base(StatisticsPaymentType.UnsupportedCard)
{
}
}
public class FuelCardLog : CardLog
{
public FuelCardLog()
: base(StatisticsPaymentType.FuelCard)
{
}
}
public class CashLog : PaymentLogBase
{
public CashLog()
: base(StatisticsPaymentType.Cash)
{
}
}
public class ITicketLog : NumberedLog
{
public ITicketLog()
: base(StatisticsPaymentType.Iticket)
{
}
}
internal class PaymentLogConverter : JsonConverter
{
public override bool CanConvert(Type t) => t.IsAssignableFrom(typeof(PaymentLogBase));
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null || !CanConvert(t)) return null;
try
{
JObject jo = JObject.Load(reader);
// following is to avoid use of magic strings
var typePropertyName = ((MemberExpression)((Expression<Func<PaymentLogBase, StatisticsPaymentType>>)(s => s.Type)).Body).Member.Name;
object target = null;
JToken jt = jo.GetValue(typePropertyName, StringComparison.InvariantCultureIgnoreCase);
var propValue = jt.ToObject<StatisticsPaymentType>();
switch (propValue)
{
case StatisticsPaymentType.FuelCard:
target = new FuelCardLog();
break;
case StatisticsPaymentType.ContactCc:
target = new CreditCardContactLog();
break;
case StatisticsPaymentType.ContactLessCc:
target = new CreditCardContactLessLog();
break;
case StatisticsPaymentType.Iticket:
target = new ITicketLog();
break;
case StatisticsPaymentType.UnsupportedCard:
target = new UnsupportedCardLog();
break;
case StatisticsPaymentType.Cash:
target = new CashLog();
break;
default:
target = null;
break;
}
if (target != null)
{
serializer.Populate(jo.CreateReader(), target);
}
return target;
}
catch (Exception ex)
{
throw new Exception("Can`t unmarshal type StatisticsPaymentType");
}
}
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
{
if (untypedValue == null)
{
serializer.Serialize(writer, null);
return;
}
try
{
serializer.Serialize(writer, untypedValue);
}
catch (Exception ex)
{
throw new Exception("Can`t marshal type StatisticsPaymentType");
}
}
public static readonly PaymentLogConverter Singleton = new PaymentLogConverter();
}
,当我将转换器指定为这样的属性时:
[JsonConverter(typeof(PaymentLogConverter))]
public abstract class PaymentLogBase
并尝试序列化这样的模型列表:
var list = new List<PaymentLogBase>();
list.Add(new CashLog());
list.Add(new CreditCardContactLessLog());
list.Add(new ITicketLog());
var json = JsonConvert.SerializeObject(list);
我进入例外:
Self referencing loop detected with type 'CashLog'. Path '.'.
当我像这样明确指定转换器时:
public static JsonSerializerSettings SerializerSettings => new JsonSerializerSettings()
{
Converters = {
PaymentLogConverter.Singleton
}
};
并使用以下设置:
var json = JsonConvert.SerializeObject(list, SerializerSettings);
它做得很好,但是在传输数据的情况下,我无法应用这种使用方法,在服务器端,我还应该明确指定转换器
我该如何解决?