我在方法JsonTypeConverter.ConvertTo
中收到StackOverflowException
调用 Project.Settings.Default.Save()
我认为这是因为方法 JsonConvert.SerializeObject
检测模型类型上的 typeconverter 并在内部调用它......
正确的写法是什么? (我能想到的唯一方法是将字符串存储在设置中并手动进行序列化/反序列化...)
public class JsonTypeConverter<TModel> : TypeConverter
{
#region Overrides of TypeConverter
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(string);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is string strValue) {
return JsonConvert.DeserializeObject<TModel>(strValue);
}
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string) && value is TModel model) {
return JsonConvert.SerializeObject(model, Formatting.None);
}
return base.ConvertTo(context, culture, value, destinationType);
}
#endregion
}
namespace Model {
[TypeConverter(typeof(JsonTypeConverter<DataModel>))]
[SettingsSerializeAs(SettingsSerializeAs.String)]
public class DataModel {
public string Value { get; set; }
}
}
“Properties/Settings.settings”的内容:
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="Builder.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="DataSource" Type="Model.DataModel" Scope="User">
<Value Profile="(Default)" />
</Setting>
</Settings>
</SettingsFile>
PS:对此问题标题有什么建议吗?
最佳答案
问题在于,JsonConverter
和 SettingsSerializer 都使用 TypeConverter
属性来告诉它们如何序列化对象。当 JsonConverter 尝试序列化对象时,它最终会通过自定义转换器再次调用自身,并最终导致堆栈溢出。
要在转换器中解决此问题,您必须告诉 JsonConverter
不要使用 TypeConverterAttribute
类型,而只执行默认的对象序列化。这是我发现完成此任务的方法:
public class JsonTypeConverter<TModel> : TypeConverter
{
/* rest of your class ... */
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is string strValue)
{
return JsonConvert.DeserializeObject<TModel>(strValue, new JsonSerializerSettings
{
ContractResolver = new CustomContractResolver(),
});
}
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string) && value is TModel model)
{
return JsonConvert.SerializeObject(model, new JsonSerializerSettings
{
ContractResolver = new CustomContractResolver(),
});
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
class CustomContractResolver : DefaultContractResolver
{
protected override JsonContract CreateContract(Type objectType)
{
if (typeof(DataModel).IsAssignableFrom(objectType))
{
return this.CreateObjectContract(objectType);
}
return base.CreateContract(objectType);
}
}
关于c# - JsonConvert.SerializeObject + TypeConverter = StackOverflowException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46186666/