1

I'm trying to create a function to automatically parse protobuf byte array and return an object no matter the type. All protobuf classes extend the IMessage interface, so I should be able to return IMessage type.

public IMessage Deserialize(int key, byte[] bytes) 
{ ... }

In Java I just keep track of all the parsers by key and pull the right one out when needed:

public final Map<Integer, Parser<? extends Message>>  parsersByKey
    = new HashMap<Integer, Parser<? extends Message>> () {{
        put(1, HiMessage.parser());
    }};


public Message parser(int key, byte[] data) {
    Parser<? extends Message> parser = parsersByKey.get(key);
    Message message = parser.parseFrom(data);
    return message;
}

But in C# I'm having two issues:

  • I can't store a dictionary of parsers since there are no anonymous types: IDictionary<int, IMessage<?>> (doesn't compile).
  • Even if I could store in a dictionary, I'm struggling to define a MessageParser<??> parser = ... to do the parsing.

Since they are all the same type family (IMessage), I should be able to do this. Each parser knows how to parse its type and using ints and keys should allow me to get the right parser.

What's the right way to get this to work? Or if it doesn't, is there a way to use generics without declaring the type?

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Jason
  • 13,563
  • 15
  • 74
  • 125
  • Can't you just do `IMessage`, as long as it is the base class it should work. – kevintjuh93 Sep 25 '15 at 12:51
  • I tried to define a `MessageParser parser;` but it's giving me a compile error since `MessageParser` is expecting a generic `IMessage`. Here's the class definition: `public sealed class MessageParser where T : Google.Protobuf.IMessage` – Jason Sep 25 '15 at 12:55
  • Why is it expecting a generic? O_O – kevintjuh93 Sep 25 '15 at 12:57
  • `IMessage` is another interface implementing `IMessage` – Jason Sep 25 '15 at 13:00
  • I'm looking at this: http://stackoverflow.com/questions/612689/a-generic-list-of-anonymous-class Is that of any help? – Nebula Sep 28 '15 at 06:44

1 Answers1

0

You could try:

public readonly Dictionary<Integer, Parser<IMessage>> parsersByKey = new Dictionary<Integer, Parser<IMessage>>
{
    {1, new HiMessage()}
};

But that would mitigate the need for the generic. So that could lead to:

public interface IParser 
{
    Message parseFrom(byte[] data);
}

public readonly Dictionary<int, IParser>  parsersByKey= new Dictionary<int, IParser>
{
    {1, new HiMessageParser() }
};

What would be your angle on using a generic for that?

Nebula
  • 1,045
  • 2
  • 11
  • 24
  • It looks like you posted Java code. The Java solution works great, but the C# one does not. – Jason Sep 25 '15 at 13:01
  • ah yeah, I was a bit too quick with posting. The idea is the same though – Nebula Sep 25 '15 at 13:06
  • I cannot change the `MessageParser` class since it's part of the generated code created with protobufs. I could create another parser class though, but I was hoping for a more `generic` solution. – Jason Sep 25 '15 at 13:07
  • The idea being that with type erasure the Java code should be just as valid in C# – Jason Sep 25 '15 at 13:08
  • I don't think you can use generics in C# without specifying the type. I ran into that one too recently. But functionally I don't see the difference? What would you need that would require generics functionality? – Nebula Sep 25 '15 at 13:11