我有一个通用类型,它将单个基本类型包装起来,以赋予其值相等的语义。
public class ValueObject<T>
{
public T Value { get; }
public ValueObject(T value) => Value = value;
// various other equality members etc...
}
这是一个示例用法:
public class CustomerId : ValueObject<Guid>
{
public CustomerId(Guid value) : base(value) { }
}
public class EmailAddress : ValueObject<string>
{
public EmailAddress(string value) : base(value) { }
}
问题在于序列化类似以下类型的内容:
public class Customer
{
public CustomerId Id { get; }
public EmailAddress Email { get; }
public Customer(CustomerId id, EmailAddress email)
{
Id = id;
Email = email;
}
}
每个从
ValueObject<T>
继承的对象都被包装在一个 Value
属性中(如预期的那样)。例如:var customerId = new CustomerId(Guid.NewGuid());
var emailAddress = new EmailAddress("some@email.com");
var customer = new Customer(customerId, emailAddress);
var customerAsJson = JsonConvert.SerializeObject(customer, Formatting.Indented, new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
})
结果在
{
"id": {
"value": "f5ce21a5-a0d1-4888-8d22-6f484794ac7c"
},
"email": {
"value": "some@email.com"
}
}
有没有一种方法可以编写自定义的
JsonConverter
,使得对于子类化ValueObject&lt; T&gt;
类型的值,Value
属性被排除在外,这样上面的示例将输出{
"id": "f5ce21a5-a0d1-4888-8d22-6f484794ac7c",
"email": "some@email.com"
}
我希望有一个通用的JsonConverter
来处理所有ValueObject<T>
,而不是为每个ValueObject<T>
子类定义单独的JsonConverter
。
我的第一次尝试是:
public class ValueObjectOfTConverter : JsonConverter
{
private static readonly Type ValueObjectGenericType = typeof(ValueObject<>);
private static readonly string ValuePropertyName = nameof(ValueObject<object>.Value);
public override bool CanConvert(Type objectType) =>
IsSubclassOfGenericType(objectType, ValueObjectGenericType);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// converts "f5ce21a5-a0d1-4888-8d22-6f484794ac7c" => "value": "f5ce21a5-a0d1-4888-8d22-6f484794ac7c"
var existingJsonWrappedInValueProperty = new JObject(new JProperty(ValuePropertyName, JToken.Load(reader)));
return existingJsonWrappedInValueProperty.ToObject(objectType, serializer);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
// to implement
}
private static bool IsSubclassOfGenericType(Type typeToCheck, Type openGenericType)
{
while (typeToCheck != null && typeToCheck != typeof(object))
{
var cur = typeToCheck.IsGenericType ? typeToCheck.GetGenericTypeDefinition() : typeToCheck;
if (openGenericType == cur) return true;
typeToCheck = typeToCheck.BaseType;
}
return false;
}
}
JsonConverter
,就像Json.Net: Serialize/Deserialize property as a value, not as an object中所示的那样。但是使用转换器有时可能会干扰多态性和TypeNameHandling
。您是否在需要保留原始类型信息的情况下使用ValueObject<T>
?为什么只针对继承ValueObject<T>
的类型? - dbcJsonConverter.CanConvert
方法吗? - dbc