I am trying to serialize into protobuf format a C# class that has properties on it that are domain specific types. But these types should be handled as value types.
I am using protobuf.net.
An example is this
[ProtoContract]
public class TestClass
{
[ProtoMember(1)]
public string StringProperty { get; set; }
[ProtoMember(2)]
public DomainTypeToBeHandldedAsString DomainTypeToBeHandldedAsString { get; set; }
}
public class DomainTypeToBeHandldedAsString
{
public string Value { get; set; }
public static implicit operator string(DomainTypeToBeHandldedAsString domainType)
{
return domainType?.Value;
}
public static implicit operator DomainTypeToBeHandldedAsString(string s)
{
return new DomainTypeToBeHandldedAsString {Value = s};
}
}
In the serialized message I do not want people to care about DomainTypeToBeHandldedAsString. I just want them to see a string and send a string.
So I tried doing this:
var model = ProtoBuf.Meta.RuntimeTypeModel.Default;
model.Add(typeof(DomainTypeToBeHandldedAsString), false).SetSurrogate(typeof(string));
But this fails with this exception:
System.ArgumentException: 'Repeated data (a list, collection, etc) has inbuilt behaviour and cannot be used as a surrogate'
Is there a way to specify a custom serializer for such a class? And it should be said that there are also domain types that should be treated as int or other value types. So not just string.
Thanks
EDIT
I tried this in addition:
[ProtoContract]
public class TestClass
{
[ProtoMember(1)]
public string StringProperty { get; set; }
public DomainTypeToBeHandldedAsInt DomainTypeToBeHandldedAsInt { get; set; }
}
[ProtoContract]
public class DomainTypeToBeHandldedAsInt : IConvertible
{
[ProtoMember(1)]
public int Value { get; set; }
public static implicit operator int(DomainTypeToBeHandldedAsInt domainType)
{
return domainType?.Value ?? 0;
}
public static implicit operator DomainTypeToBeHandldedAsInt(int s)
{
return new DomainTypeToBeHandldedAsInt { Value = s };
}
public int ToInt32(IFormatProvider provider)
{
return Value;
}
//All the rest throw a NotImplementedException
}
I then added the type to the RunTimeModel like this:
var model = ProtoBuf.Meta.RuntimeTypeModel.Default;
model[typeof(TestClass)].Add(2, "DomainTypeToBeHandldedAsInt", typeof(Int32), null);
And that resulted in a .proto file like this:
syntax = "proto3";
package ProtoBufferSerializerTest;
message TestClass {
string StringProperty = 1;
repeated int32 DomainTypeToBeHandldedAsInt = 2 [packed = false];
}
But I do not want this to be repeated and I don't need the [packed = false] either.