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