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