我正在尝试实现一个自定义 JSON.net IContractResolver,它将用指定的字符串替换所有空属性值。我知道此功能可以通过序列化类型成员的属性获得;这是我们正在考虑的替代路线。
到目前为止,我的解析器实现如下。StringValueProvider 是 IValueProvider 的简单实现,它不会影响问题,即我无法弄清楚如何获取property
的值,因为我对提供member
的实例的此方法一无所知,所以我无法将其作为参数传递给GetValue()
(在代码示例中标记为 WHAT-GOES-HERE?
有没有办法从member
或property
那里得到我需要的东西?
public class NullSubstitutionPropertyValueResolver : DefaultContractResolver
{
private readonly string _substitutionValue;
public NullSubstitutionPropertyValueResolver(string substitutionValue)
{
_substitutionValue = substitutionValue;
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty result = base.CreateProperty(member, memberSerialization);
PropertyInfo property = member as PropertyInfo;
if (property == null)
{
return result;
}
// What do I use here to get the property value?
bool isNull = property.GetValue(WHAT-GOES-HERE?) == null;
if (isNull)
{
result.ValueProvider = new StringValueProvider(_substitutionValue);
}
return result;
}
}
合约解析器不关心实例,它关心类型。 值提供程序与实例有关。 在协定解析程序中,您可以根据属性类型决定是否应将值提供程序应用于属性(例如,也许您只想对string
属性使用StringValueProvider
? 然后,使值提供程序存储对属性的引用(将其与替换值一起传递到构造函数中)。 在值提供程序中,可以从对象实例中读取值,检查它是否为 null 并执行适当的值替换。
代码应如下所示:
public class NullSubstitutionPropertyValueResolver : DefaultContractResolver
{
private readonly string _substitutionValue;
public NullSubstitutionPropertyValueResolver(string substitutionValue)
{
_substitutionValue = substitutionValue;
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty result = base.CreateProperty(member, memberSerialization);
PropertyInfo property = member as PropertyInfo;
if (property.PropertyType == typeof(string))
{
result.ValueProvider = new StringValueProvider(property, _substitutionValue);
}
return result;
}
}
public class StringValueProvider : IValueProvider
{
private PropertyInfo _targetProperty;
private string _substitutionValue;
public StringValueProvider(PropertyInfo targetProperty, string substitutionValue)
{
_targetProperty = targetProperty;
_substitutionValue = substitutionValue;
}
// SetValue gets called by Json.Net during deserialization.
// The value parameter has the original value read from the JSON;
// target is the object on which to set the value.
public void SetValue(object target, object value)
{
_targetProperty.SetValue(target, value);
}
// GetValue is called by Json.Net during serialization.
// The target parameter has the object from which to read the value;
// the return value is what gets written to the JSON
public object GetValue(object target)
{
object value = _targetProperty.GetValue(target);
return value == null ? _substitutionValue : value;
}
}
这是一个工作演示:https://dotnetfiddle.net/PAZULK