I have a class:
internal class Value
{
internal IConvertible Min { get; set; }
}
and a test case:
[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);
}
that throws:
System.InvalidOperationException: Unexpected sub-type: System.Boolean
But I cannot add boolean as a subtype of IConvertible, because I will get:
System.ArgumentException: Data of this type has inbuilt behaviour, and
cannot be added to a model in this way: System.Boolean
As I see it, IConvertible is only implemented by BCL base types and this scenario should be working just OK. What am I missing here?
Inspired by Marc's response below, I rewrote my sample.
Having a class:
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; }
}
}
}
and a test case:
[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);
}
I get an exception when calling Add(1, "Min"):
System.ArgumentException: Unable to determine member: Min
Parameter name: memberName
However, it will work just fine if I were to define a class as (same code, but with attributes):
[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);
}
but I cannot use attributes.
Is it a bug or I'm missing something obvious?