C# 在不编辑类的情况下获得“JsonConstructor”的效果

C# 在不编辑类的情况下获得“JsonConstructor”的效果,c#,json.net,C#,Json.net,我有一些具有只读属性和构造函数的类,例如: public class MyClass { public string Foo { get; } public bool Bar { get; } public MyClass(string foo); public MyClass(string foo, bool bar); } 它将序列化,但反序列化对象将失败 Newtonsoft.Json.JsonSerializationException:找不到用于MyC

我有一些具有只读属性和构造函数的类,例如:

public class MyClass
{
    public string Foo { get; }
    public bool Bar { get; }
    public MyClass(string foo);
    public MyClass(string foo, bool bar);
}
它将序列化,但
反序列化对象
将失败

Newtonsoft.Json.JsonSerializationException:找不到用于MyClass类型的构造函数。一个类应该有一个默认构造函数、一个带参数的构造函数或一个标记有JsonConstructor属性的构造函数。路径“…”,第1行,位置1

添加
jsonstructor
属性将起作用,但有时我无法控制源代码的类型。我是否可以告诉转换器以其他方式处理属性


理想情况下,无需在
JsonConverter.ReadJson
中手动执行每种类型的参数。

进行了一些研究,看起来您可以在反序列化过程中使用自定义
JsonContractResolver
,这将为序列化程序提供正确的对象创建者。
因此,反序列化看起来像:

var settings=newjsonserializersettings{ContractResolver=newmycontractResolver()};
var myClass=JsonConvert.DeserializeObject(“{\'Foo\':\'Hello\',\'Bar\':true}”,设置);
MyContractResolver
是:

公共类MyContractResolver:DefaultContractResolver
{
公共重写JsonContract ResolveContract(类型)
{
var合同=基本合同(类型);
如果(type==typeof(MyClass)&&contract为JsonObjectContract-objectContract)
{
objectContract.OverrideCreator=(args)=>new MyClass((字符串)args[0],(bool)args[1]);
var overrideConstructor=typeof(MyClass).GetConstructor(新[]{typeof(string),typeof(bool)});
foreach(CreateConstructorParameters(overrideConstructor,objectContract.Properties)中的var参数)
objectContract.CreatorParameters.Add(参数);
}
退货合同;
}
}
当然,这是非常简单的,而且
JsonSerializer
属性使用起来更方便。但是,如果您有遗留类,这可能会有所帮助


其思想是,当
序列化程序
为您的类型填充
JsonContract
时,让默认的契约解析器构建它,然后注入您实际需要在契约的
重写创建者
属性中调用的构造函数,在
CreatorParameters

中对其参数的描述我对您的问题没有答案,但作为一种解决方法,没有什么能强迫您反序列化到该特定类型。您还可以反序列化到自己的类型,甚至是匿名类型,然后将结果映射到实际的目标类型。当然,这需要编写一些代码,但自定义json转换器也需要编写一些代码……这与为每种类型编写每个参数非常相似。。。我可能可以通过反射来编写一个通用的解决方案(我假设Json.Net在内部是这样做的)。但是如果你可以说“使用这个构造函数
typeA,typeB
”或者“假装它在成员y上有这个属性x”,那么你就不想重新发明了。似乎是下注的方法。在该代码中,有一个可重写的
CreateObjectContract
。它实际上使用
GetAttributeConstructor
查找属性,但它似乎不可重写,似乎
DefaultContractResolver
处理一组属性。