2

我想我在 ServiceStack.Text 中发现了一个错误。我将此测试(如下)添加到 CustomSerializerTests 文件中。您会注意到它适用于反序列化单个项目,但在反序列化 (i) 列表时不会调用构造函数。(从 IList 更改为 List 使测试通过。)如何使用 IList 进行这项工作?

更新:在进一步查看 ReflectionExtensions 时,我不明白您为什么将“New”与“CreateInstance”区分开来。如果可能,所有对 CreateInstance 的调用都应该使用 ModelFactory,对吗?看起来创建实例的方法比必要的要多。

更新 2:我一直在研究重构 ReflextionExtensions 以使其工作。但是,我似乎看不到使其适用于所有现有测试的方法。ModelFactory 的一些现有测试调用 ReflextionExtensions.CreateInstance 方法。我为使这项工作所做的任何更改都会导致 CreateInstance 使用 ModelFactory。因此,我们对那些现有的测试进行了无限循环。如果测试返回 ModelFactory 的默认值而不是直接调用 CreateInstance,它会起作用。

class MyImmutable
{
    public readonly double Const = 42;
    public double Value { get; protected set; }
    protected MyImmutable() {} // for serialization
    public MyImmutable(double value)
    {
        Value = value;
    }
}

[Test]
public void ProtectedConstructorsAreCalled()
{
    using (JsConfig.With(modelFactory: type =>
    {
        if (type.IsValueType)
            return () => Activator.CreateInstance(type);

        var ctors = from ctor in type.GetConstructors(BindingFlags.Instance | BindingFlags.Public)
                    let prms = ctor.GetParameters()
                    where prms.All(p => p.IsOptional)
                    orderby prms.Length
                    select ctor;

        var constructor = ctors.FirstOrDefault();

        if (constructor == null)
        {
            ctors = from ctor in type.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)
                    let prms = ctor.GetParameters()
                    where prms.All(p => p.IsOptional)
                    orderby prms.Length
                    select ctor;

            constructor = ctors.FirstOrDefault();
        }

        if (constructor != null)
            return () => constructor.Invoke(new object[0]);

        throw new NotSupportedException();
    }))
    {
        var immut = new MyImmutable(23);
        var json = immut.ToJson();
        var immut2 = json.FromJson<MyImmutable>();

        Assert.AreEqual(immut.Const, immut2.Const); // this assert is fine
        Assert.AreEqual(immut.Value, immut2.Value);

        IList<MyImmutable> immutables = new List<MyImmutable>{immut};

        json = immutables.ToJson();
        var immutables2 = json.FromJson<IList<MyImmutable>>();

        for (int i = 0; i < immutables.Count; i++)
        {
            Assert.AreEqual(immutables[i].Const, immutables2[i].Const); // fails on this assert
            Assert.AreEqual(immutables[i].Value, immutables2[i].Value);
        }
    }
}
4

0 回答 0