2
votes

I'm using the protobuf-net library to speed up wcf serialization and now I've come to a problem with derived classes. I looked into several discussions about class derivation but none fits my problem.

I'm using the following base:

[DataContract, ProtoContract]
//[ProtoInclude(10000, typeof(SysLoginRequest))]
public class ServiceRequest
{
    public ServiceRequest()
    {
        // No parameterless constructor found for ServiceRequest?
        RuntimeTypeModel.Default.Add(typeof(ServiceRequest), true).AddSubType(10000, typeof (SysLoginRequest));
    }
}

And the derived class:

[DataContract, ProtoContract]
public class SysLoginRequest : ServiceRequest, IServiceRequest<SysLoginResponse>
{
    [DataMember(Order = 1, IsRequired = true)]
    public string UserSid { get; set; }

    [DataMember(Order = 2, IsRequired = true)]
    public string UserName { get; set; }

    [DataMember(Order = 3, IsRequired = true)]
    public string Password { get; set; }

    [DataMember(Order = 4, IsRequired = true)]
    public string IpAddress { get; set; }

    [DataMember(Order = 5)]
    public string ProcessName { get; set; }

    [DataMember(Order = 6)]
    public int ProcessId { get; set; }
}

What I'm trying to do is to get away from attributes by adding the subclasses at runtime but in my test I always get the runtime error that there is no parameterless constructor for the base class? I tried to make the constructor static but that didn't help either.

If I use the attribute (and remove the constructor) everything is fine, but if I do it using the RuntimeTypeModel I get the error message. What am I doing wrong here?

1
You should put your update as an answer and then accept it, that way people can upvote your answer and stackoverflow will mark your question as solved for you (right now it's still officially unsolved) - Daniel Gratzer
Yes, but I'm new to stackoverflow and had to wait until I can answer my own question. :) - Citiga

1 Answers

2
votes

Ok, I got it working now. There was a problem with mixed initialization. I still had some ProtoInclude-decorators on some classes and tried to add subtypes by using the RuntimeTypeModel.

I ended up with a small initialisation class:

public static class ProtoBufInitializer
{
    private static readonly object ClassSync = new object();

    private static bool _initialized;

    public static void Initialize()
    {
        lock (ClassSync)
        {
            if (!_initialized)
            {
                ProcessTypes<ServiceRequest>();
                ProcessTypes<ServiceResponse>();
                _initialized = true;
            }
        }
    }

    private static void ProcessTypes<T>()
    {
        int tag = 10000;
        foreach (var type in ReflectionUtils.FindAllDerivedTypes<T>())
        {
            if (type.IsClass && !type.IsAbstract)
                RuntimeTypeModel.Default.Add(typeof (T), true).AddSubType(tag++, type);
        }
    }
}

Another problem resulted from changing the RuntimeTypeModel after using the protobuf-net serializsation.