views:

85

answers:

4

For a fun project I'm trying to implement the BitTorrent spec, and right now I'm working on the BEncoding portion of it.

The encoding basically can encode from int/string/dictionary -> string for transmission. I've got all of the different encodings written/tested/working as overloaded Encode(...) methods and I've got the individual decode methods written/tested/working as DecodeString(...), DecodeInt(...) etc.

I can't figure out a way to have 1 Decode method for all decodings, in order to keep the API for the encoding/decoding as clean as possible (2 public methods, tops, for the time being).

Note that I have a method that can get the type of result that the decoded string will have.

Client code, right now would have to look something like this every time they want to decode a message:

string s = ...; // Encoded string
Type t = Encoder.GetDecodedType(s);
if (t == typeof(int))
    process(Encoder.DecodeInt(s));
else if (t == typeof(string))
    process(Encoder.DecodeString(s));
else if (t == typeof(Dictionary<string, string>))
    process(Encoder.DecodeStringDictionary(s));
else if (t == typeof(Dictionary<string, int>))
    process(Encoder.DecodeIntDictionary(s)):

and I'd like to be able to clean that up to be more like:

string s = ...; // Encoded string
process(Encoder.Decode(s));

where, in both cases the process(...) would likely be overloaded functions at the client end taking the 4 types of decoded values.

A: 

I would say that you should follow the Liskov Substitution Principle here and create a method for each data type. That way you don't keep adding to the misery of utilizing typeof when you start passing custom objects. After reading over your question again, you already know the type being passed to it, so that further supports the need to remove the typeof operation

Woot4Moo
A: 

I'm confused. why not simply perform the GetDecodedType logic in the public Decode method and determine the type and then make the varying calls once determined?

Aaron
Because I can't know the return type of the Decode method that will call GetDecodedType at design time.
SnOrfus
Is this via a WS? DLL? How is the client executing these methods? If it is via WS, the return type has to be defined, and unless you are going to create a custom type which encapsulates the multiple types (redundant in a different way), it seems having multiple methods for each type is the way to go...per Woot4Moo
Aaron
@Aaron: it's a DLL, and the client code will mostly be mine, but it'll eventually (once something is usable) end up being an open source project so I'd like to have as clean an API as possible. If what @Timwi posted won't work, then I'l likely have to go with what I have already (multiple methods).
SnOrfus
+3  A: 

You could let the DLR do this for you.

public static void Process(int i) { ... }
public static void Process(string s) { ... }
public static void Process(Dictionary<string, string> dic) { ... }
public static void Process(Dictionary<string, int> dic) { ... }

[...]

public dynamic Decode(string input)     // or 'object' if you prefer
{
    var t = GetDecodedType(input);
    if (t == typeof(int))
        return DecodeInt(input);
    else if (t == ...)
        // ...
}

[...]

string s = ...; // Encoded string
Process(Encoder.Decode(s));            // if you used 'dynamic' above
Process((dynamic)Encoder.Decode(s));   // if you used 'object' above
Timwi
Dang, beat me to it.
Scott Chamberlain
Ooh. That looks sexy. I'll look it up, but is there a framework version dependency in order to use dynamic?
SnOrfus
@SnOrfus: I’m afraid it does require .NET 4.0 or above, yeah.
Timwi
@Timwi: That's fine, I was originally working in 3.5, but I'm not tied to a particular version.
SnOrfus
Works like a dream. Thanks @Timwi
SnOrfus
+1  A: 

If you are writing a library/framework ... this will be the most invaluable resource in your endeavor :-) I have the hardcopy and read it cover to cover:
Design Guidelines for Developing Class Libraries from Microsoft

Joel Martinez
+1: That's a great resource that I wasn't aware of. I'll definitely be devouring that tonight. Thanks Joel.
SnOrfus