1

我需要为新的 PoC 提供带有一些虚假数据的 Web API 服务。这个对象模型非常简单,有 2 个类,其中 class1 有一个嵌套数组 class2。所以我开始构建一个 FakeDataService,我只是在其中硬编码了一些数据。为简洁起见,我省略了很多属性,因此代码重点关注问题的本质:

public class Class1
{
    public string Prop1 { get; set; }
    public IEnumerable<Class2> Prop2 { get; set; }
    public IEnumerable<string> Prop3 { get; set; }
}    

public class Class2
{
    public string Prop4 { get; set; }
}

public static class FakeDatabase
{
    public static Class1 c1instance1 = new Class1 { Prop1 = "value1", 
                          Prop2 = new Class2[] { c2instance1 }, 
                          Prop3 = new string[] { "value3" } };

    public static Class2 c2instance1 = new Class2 { Prop4 = "Value4" };

    public static Class1[] AllData = new Class1[] { c1instance1 };

}

所以,我的假数据库的“AllData”是一个 Class1 对象数组(本例中只有一个“数组”),Class1 对象有一个字符串属性(prop1)、一个 Class2 对象数组(prop2)和一个字符串属性数组 (prop3),而 Class2 对象只有一个字符串属性 (prop4)。

WebAPI 控制器是最基本的:

public class ValuesController : ApiController
{

    // GET api/values
    public IEnumerable<Class1> Get()
    {
        return FakeDatabase.AllData;                                                                                                                                                                                       
    }

但是当我调用 Values 控制器时,结果是:

<ArrayOfClass1 xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/FakeDataService.Models">
<Class1>
<Prop1>value1</Prop1>
<Prop2>
<Class2 i:nil="true"/>
</Prop2>
<Prop3 xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d3p1:string>value3</d3p1:string>
</Prop3>
</Class1>
</ArrayOfClass1>

注意 Class2 对象的序列化如何产生 i:nil=true

经过几个小时的搜索(我的示例数据比这里的这个简单示例大很多),我发现问题的根源在于嵌套对象数组被定义为静态实例。例如。将 FakeDatabase 的初始代码更改为:

public static class FakeDatabase
    {
        public static Class1 c1instance1 = new Class1 { Prop1 = "value1", 
                Prop2 = new Class2[] { new Class2 { Prop4 = "Value4" }},
                Prop3 = new string[] { "value3" } };


        public static Class1[] AllData = new Class1[] { c1instance1 };

}

现在调用 WebAPI 控制器给了我(正确):

<ArrayOfClass1 xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/FakeDataService.Models">
<Class1>
<Prop1>value1</Prop1>
<Prop2>
<Class2>
<Prop4>Value4</Prop4>
</Class2>
</Prop2>
<Prop3 xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d3p1:string>value3</d3p1:string>
</Prop3>
</Class1>
</ArrayOfClass1>

所以唯一的区别是 Class2 对象的数组。这种行为的解释是什么?

4

1 回答 1

0

您的问题是您c2instance1在初始化之前使用了静态变量。来自C# Language Specification §10.4.5.1 静态字段初始化

类的静态字段变量初始化器对应于一系列赋值,它们按照它们在类声明中出现的文本顺序执行。

因此,在您的FateDatabase类中,c1instance1初始化器使用c1instance1while 它仍然为空:

public static class FakeDatabase
{
    public static Class1 c1instance1 = new Class1
    {
        Prop1 = "value1",
        Prop2 = new Class2[] { c2instance1 }, // NOT INITIALIZED YET, THUS NULL
        Prop3 = new string[] { "value3" }
    };

    public static Class2 c2instance1 = new Class2 { Prop4 = "Value4" };

    public static Class1[] AllData = new Class1[] { c1instance1 };
}

翻转静态变量的文本顺序以修复错误:

public static class FakeDatabase
{
    public static Class2 c2instance1 = new Class2 { Prop4 = "Value4" };

    public static Class1 c1instance1 = new Class1
    {
        Prop1 = "value1",
        Prop2 = new Class2[] { c2instance1 },
        Prop3 = new string[] { "value3" }
    };

    public static Class1[] AllData = new Class1[] { c1instance1 };
}
于 2015-07-03T03:13:50.507 回答