2

ServiceStack.Text でバグを見つけたと思います。このテスト (以下) を CustomSerializerTests ファイルに追加しました。単一のアイテムを逆シリアル化する場合は機能しますが、(i)list を逆シリアル化する場合、コンストラクターは呼び出されません。(IList から List に変更すると、テストに合格します。) これを IList で機能させるにはどうすればよいですか?

更新: ReflectionExtensions をさらに調べたところ、「新規」と「CreateInstance」を区別する理由がわかりません。CreateInstance へのすべての呼び出しは、可能であれば ModelFactory を使用する必要があります。本当ですか? インスタンスを作成するためのメソッドが必要以上にあるようです。

更新 2: これを機能させるために ReflextionExtensions をリファクタリングすることを検討しています。ただし、既存のすべてのテストで機能させる方法がわかりません。ModelFactory の既存のテストの中には、ReflextionExtensions.CreateInstance メソッドを呼び出すものがあります。これを機能させるために変更すると、CreateInstance が ModelFactory を使用することになります。したがって、これらの既存のテストで無限ループに入ります。テストが CreateInstance を直接呼び出すのではなく、ModelFactory のデフォルト値を返した場合、それは機能します。

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