为什么ServiceStack.Text没有将ModelFactory用于列表?

时间:2013-10-24 14:59:16

标签: c# reflection servicestack servicestack-text

我想我在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);
        }
    }
}

0 个答案:

没有答案
相关问题