0

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.

Geoxion
  • 448
  • 1
  • 4
  • 14
  • The search term you probably were missing is "c# generic method makegenericmethod". – usr May 30 '14 at 16:56
  • @usr, what made you think this question was just about trying to call a generic method with reflection? I think you are mistaken. He is trying to correlate an enum with a `Type`, which is quite different. – Kirk Woll May 30 '14 at 18:32
  • @KirkWoll Below "Essentially what I want to do is:" he says he wants to dynamically supply a generic type parameter. This seems to be the missing piece for him. I'll leave this open. – usr May 30 '14 at 18:40
  • @KirkWoll look at the answer that has arrived. It is just like the top answer in the ~20 duplicates I have today closed that all are about MakeGenericMethod. Tiny variations. The variation here is that he doesn't have a Type but a string that is the name of the Type. – usr May 30 '14 at 20:57
  • @usr, the issue is how to get the type argument, which The Dutch Man addresses, but which the other alleged duplicates did not. – Kirk Woll May 30 '14 at 21:03

1 Answers1

2

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.

Jevgeni Geurtsen
  • 3,133
  • 4
  • 17
  • 35