Elegant way to connect an enum value to a method group

222 Views Asked by At

I'm creating a networked application. For this I'm creating a messaging system. What I've got so far (a snippet at least...)

public static byte[] ClassToBytes(GenericMessage Data)
{
    int Size = Marshal.SizeOf(Data);
    byte[] Buffer = new byte[Size];
    IntPtr Ptr = Marshal.AllocHGlobal(Size);

    Marshal.StructureToPtr(Data, Ptr, true);
    Marshal.Copy(Ptr, Buffer, 0, Size);
    Marshal.FreeHGlobal(Ptr);

    return Buffer;
}

public static GenericMessage BytesToClass(byte[] Source, ClassType Type)
{
    switch (Type) //This is going to be extended
    {
        case ClassType.GenericMessage:
            return BytesToClass<GenericMessage>(Source);
            break;
        case ClassType.RequestMessage: //RequestMessage is derived from GenericMessage
            return BytesToClass<RequestMessage>(Source);
            break;
        case ClassType.ResponseMessage: //ResponseMessage is derived from GenericMessage
            return BytesToClass<ResponseMessage>(Source);
            break;
        default:
            throw new KeyNotFoundException();
            break;
    }
}

public static T BytesToClass<T>(byte[] Source)
{
    int Size = Marshal.SizeOf(typeof(T));
    IntPtr Ptr = Marshal.AllocHGlobal(Size);
    Marshal.Copy(Source, 0, Ptr, Size);
    T result = (T)Marshal.PtrToStructure(Ptr, typeof(T));
    Marshal.FreeHGlobal(Ptr);
    return result;
}

Essentially what I want to do is:

public static GenericMessage BytesToClass(byte[] Source, ClassType Type)
{
    return BytesToClass<Type>(Source);  
}

Is there such a way with an enum, or maybe a dictionary?

I've tried and searched, but without any result.

1

There are 1 best solutions below

0
On BEST ANSWER

If you want to dynamically supply a generic type, as @usr commented in the comments, you can do it like this:

    public static GenericMessage BytesToClass(byte[] Source, ClassType MyType)
    {
        // Gets the Type we want to convert the Source byte array to from the Enum 
        Type _targetType = typeof(Program).GetNestedType(MyType.ToString());
        // Gets the generic convertion method, note we have to give it the exact parameters as there are 2 methods with the same name
        var _convMethod = typeof(Program).GetMethod("BytesToClass", new Type[] { typeof(byte[]) });
        // Invoke the generic method, setting T as _targetType
        var result = _convMethod.MakeGenericMethod(new Type[] { _targetType }).Invoke(null, new object[] { Source });
        return (GenericMessage)result;
    }

The ClassType enum members' names has to be exactly the same as the classes' names they represent. Also, this method assumes that the classes you want to convert the byte array into are in the Program class (see, typeof(Program)). Obviously you should change this to make it work with your program.