私はクラスを持っています:
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 のサブタイプとして boolean を追加することはできません。
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);
}
しかし、私は属性を使用できません。
それはバグですか、それとも明らかな何かが欠けていますか?