Question

I would like to write a C# client to send a string via protobuf-net to a TCP server (implemented). However, when I try to serialize the string using protobuf-net, I'm getting a TypeInitializerException "The type initializer for 'Singleton' threw an exception."

Here is the code:

public static void TelnetConnect(string host, int port) {
    ...
    Message msg = new Message("This is a test.");
    byte[] sentbytes = msg.Serialize();
    ...
}

[ProtoContract]
public abstract class MessageI {
    public byte[] Serialize() {
        byte[] result;
        using (var stream = new MemoryStream()) {
            Serializer.Serialize(stream, this);  //THIS LINE THROWS EXCEPTION
            result = stream.ToArray();
        }
        return result;
    }
}

[ProtoContract]
public class Message : MessageI {
    [ProtoMember(1)]
    public string str { get; set; }

    public Message(string s) {
        this.str = s;
    }
}

I've tried a number of approaches advised by this site and others, without success. I'm using C# on Visual Studio 2010.

Thanks, I very much appreciate your help.

UPDATE: The stack trace is:

   at ProtoBuf.Meta.RuntimeTypeModel.get_Default()
   at ProtoBuf.Serializer.Serialize[T](Stream destination, T instance)
   at PingNorbertServer.MessageI.Serialize() in C:\Users\RS88517\Documents\Visual Studio 2010\Projects\PingNorbertServer\PingNorbertServer\NorbertClient.cs:line 37
   at PingNorbertServer.NorbertClient.TelnetConnect(String host, Int32 port) in C:\Users\RS88517\Documents\Visual Studio 2010\Projects\PingNorbertServer\PingNorbertServer\NorbertClient.cs:line 23
   at PingNorbertServer.NorbertClient.Main(String[] args) in C:\Users\RS88517\Documents\Visual Studio 2010\Projects\PingNorbertServer\PingNorbertServer\NorbertClient.cs:line 14
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()
Était-ce utile?

La solution

I cannot reproduce it erroring; your code, copied directly, works fine:

static void Main()
{
    var data = new Message("abc").Serialize();
}

But, to try to help:

  • first, catch the Exception, and look at the .InnerException. More information is available for most exceptions; for example:

    try {
        // HERE: the code that errors
    } catch(Exception ex) {
        while(ex != null) {
            Console.Error.WriteLine(ex.Message);
            ex = ex.InnerException;
        }
        throw;
    }
    
  • secondly, note that a common issue with inheritance models is not declaring the inheritance - look at whether perhaps the base class needs decorating, for example:

    [ProtoInclude(1, typeof(Message))]
    
  • another observation is the lack of a public parameterless constructor; now, protobuf-net doesn't insist on that (and indeed, it looks like it is treating the code in the question as an "auto tuple", and using the constructor that exists), but you can also either provide an additional (possibly non-public) parameterless constructor:

    private Message() {}
    

    or tell it to skip the constructor completely:

    [ProtoContract(SkipConstructor = true)]
    

But: without knowing what the exception message is, it is hard to speculate further than this.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top