C# 如何反序列化不可变的数据结构?

C# 如何反序列化不可变的数据结构?,c#,yamldotnet,C#,Yamldotnet,如何将YAML反序列化为不可变的数据结构 e、 g.我有这个YAML: Value: SomeString Number: 99 这个数据结构: public class MyData { public MyData(string value, int number) { Value = value; Number = number; } public string Value { get; } public int N

如何将YAML反序列化为不可变的数据结构

e、 g.我有这个YAML:

Value: SomeString
Number: 99
这个数据结构:

public class MyData
{
    public MyData(string value, int number)
    {
        Value = value;
        Number = number;
    }

    public string Value { get; }
    public int Number { get; }
}

为此,我想使用构造函数。因此,我需要首先检索一个从YAML中解析出的关于我的类的
字典(因此99应该是int,而不是string),然后扫描我的类型以找到合适的构造函数,

使用FormatterServices.GetUninitializedObject API(这根本不会调用任何构造函数),然后使用反射来设置字段

代码示例:

 var instance = FormatterServices.GetUninitializedObject(typeof(MyData));
 var flags = BindingFlags.NonPublic | BindingFlags.Instance;
 var type = typeof(MyData);
 var stringField = type.GetField("_value", flags);

 stringField.SetValue(instance, "SomeString");

 var numberField = type.GetField("_number", flags);
 numberField.SetValue(instance, 99);

 MyData data = (MyData)instance;

使用FormatterServices.GetUninitializedObject API(这根本不会调用任何构造函数),然后使用反射设置字段

代码示例:

 var instance = FormatterServices.GetUninitializedObject(typeof(MyData));
 var flags = BindingFlags.NonPublic | BindingFlags.Instance;
 var type = typeof(MyData);
 var stringField = type.GetField("_value", flags);

 stringField.SetValue(instance, "SomeString");

 var numberField = type.GetField("_number", flags);
 numberField.SetValue(instance, 99);

 MyData data = (MyData)instance;

虽然问题没有提到,但我假设您使用的是YamlDotNet(或SharpYaml,它是YamlDotNet的一个分支)

YamlDotNet不支持反序列化到没有默认构造函数的类中,但实现此目的的一个选项是反序列化到可生成最终类型的可变中间生成器类型中。 e、 g

然后使用类似于:

deserializer.Deserialize<MyDataBuilder>(yaml).Build();
在这种情况下,我们需要另一个建筑商:

public class MyOtherDataBuilder 
{
    public string OtherValue { get; set; }
}
MyDataBuilder
看起来像:

public class MyDataBuilder
{
    public string Value { get; set; }
    public int Number { get; set; }
    public MyOtherDataBuilder MyOtherData { get; set; }
    public MyData Build() => new MyData(Value, Number, MyOtherData.Build());
}

虽然问题没有提到,但我假设您使用的是YamlDotNet(或SharpYaml,它是YamlDotNet的一个分支)

YamlDotNet不支持反序列化到没有默认构造函数的类中,但实现此目的的一个选项是反序列化到可生成最终类型的可变中间生成器类型中。 e、 g

然后使用类似于:

deserializer.Deserialize<MyDataBuilder>(yaml).Build();
在这种情况下,我们需要另一个建筑商:

public class MyOtherDataBuilder 
{
    public string OtherValue { get; set; }
}
MyDataBuilder
看起来像:

public class MyDataBuilder
{
    public string Value { get; set; }
    public int Number { get; set; }
    public MyOtherDataBuilder MyOtherData { get; set; }
    public MyData Build() => new MyData(Value, Number, MyOtherData.Build());
}

很抱歉,我想使用构造函数进行此操作。另外,您的回答也无法帮助我如何从YAML中获得适当的值。我相应地调整了我的问题,我认为这是一个关于如何将数据反序列化为不可变类型的一般性问题。你的问题现在没有意义了。只需调用构造函数:)您的问题是什么?迭代字典并为每个项创建一个新的MyData。反序列化中的整个ideea是在设置私有字段之前不调用可能操纵输入数据的构造函数。通常你需要绕过构造函数。我怀疑OP使用的是像YamlDotNet这样的库,它不支持反序列化到没有默认构造函数的类中。很抱歉,我想使用构造函数来实现这一点。另外,您的回答也无法帮助我如何从YAML中获得适当的值。我相应地调整了我的问题,我认为这是一个关于如何将数据反序列化为不可变类型的一般性问题。你的问题现在没有意义了。只需调用构造函数:)您的问题是什么?迭代字典并为每个项创建一个新的MyData。反序列化中的整个ideea是在设置私有字段之前不调用可能操纵输入数据的构造函数。通常你需要绕过构造函数,我怀疑OP使用的是类似YamlDotNet的库,它不支持反序列化到没有默认构造函数的类中。