我有一堂课:
internal class Value
{
internal IConvertible Min { get; set; }
}
和一个测试用例:
[TestMethod]
public void Custom_IConvertible()
{
RuntimeTypeModel.Default.
Add(typeof(Value), false).
Add(1, "Min");
RuntimeTypeModel.Default.
Add(typeof(IConvertible), false);
var val = new Value {Min = true};
var result = Serializer.DeepClone(val);
Assert.AreEqual(true, result.Min);
}
抛出:
System.InvalidOperationException: Unexpected sub-type: System.Boolean
但我不能将布尔值添加为 IConvertible 的子类型,因为我会得到:
System.ArgumentException: Data of this type has inbuilt behaviour, and
cannot be added to a model in this way: System.Boolean
正如我所看到的,IConvertible 仅由 BCL 基本类型实现,这种情况应该可以正常工作。我在这里想念什么?
受以下 Marc 回复的启发,我重写了我的示例。
上课:
internal abstract class Value
{
internal IConvertible Min { get; set; }
internal static Value Create<T>(T min) where T :IConvertible
{
return new ValueT<T> {Min = min};
}
internal sealed class ValueT<T> : Value where T : IConvertible
{
internal new T Min
{
get { return (T) base.Min; }
set { base.Min = value; }
}
}
}
和一个测试用例:
[TestMethod]
public void Custom_IConvertible()
{
RuntimeTypeModel.Default.
Add(typeof(Value), false).
AddSubType(10, typeof(Value.ValueT<bool>));
RuntimeTypeModel.Default.
Add(typeof(Value.ValueT<bool>), false).
Add(1, "Min");
var val = Value.Create(true);
var result = Serializer.DeepClone(val);
Assert.AreEqual(true, result.Min);
}
调用 Add(1, "Min") 时出现异常:
System.ArgumentException: Unable to determine member: Min
Parameter name: memberName
但是,如果我将一个类定义为(相同的代码,但具有属性),它将工作得很好:
[ProtoContract]
[ProtoInclude(1, typeof(ValueT<int>))]
internal abstract class Value
{
internal IConvertible Min { get; set; }
internal static Value Create<T>(T min) where T :IConvertible
{
return new ValueT<T> {Min = min};
}
[ProtoContract]
internal sealed class ValueT<T> : Value where T : IConvertible
{
[ProtoMember(1)]
internal new T Min
{
get { return (T) base.Min; }
set { base.Min = value; }
}
}
}
[TestMethod]
public void Custom_IConvertible()
{
var val = Value.Create(true);
var result = Serializer.DeepClone(val);
Assert.AreEqual(true, result.Min);
}
但我不能使用属性。
这是一个错误还是我遗漏了一些明显的东西?