A contract reporter does not deal with instances; it deals with types. The cost provider refers to instances. In the contract recognizer, you decide whether to use the value provider for the property based on the type of the property (for example, maybe you want to use only the StringValueProvider
on properties string
?). Then you make the value provider save the link to the property (pass it in the constructor along with the substitution value). In the value provider, you can read a value from an instance of an object, check if it is null, and perform an appropriate replacement of values.
The code should look something like this:
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;
}
public void SetValue(object target, object value)
{
_targetProperty.SetValue(target, value);
}
public object GetValue(object target)
{
object value = _targetProperty.GetValue(target);
return value == null ? _substitutionValue : value;
}
}
: https://dotnetfiddle.net/PAZULK