Search code examples
c#structsystem.reflection

How to call MemoryMarshal.CreateSpan using Reflection API?


Let's suppose I have this C# structure:

  public struct Test
  {
      public int Code1;
      public int Code2;
  }

This code works fine:

  var test = new Test { Code1 = 1, Code2 = 2 };
  var bytes = MemoryMarshal.AsBytes(MemoryMarshal.CreateSpan(ref test, 1));

In bytes, I will get an array of 8 bytes (1, 0, 0, 0, 2, 0, 0, 0).

Now, how can I call the same methods CreateSpan + AsBytes using Reflection API instead of a predefined/generic type?

I have tried this for the CreateSpan part:

  private static object GetBytes(object value)
  {
      var method = typeof(MemoryMarshal).GetMethod(nameof(MemoryMarshal.CreateSpan));
      var gmethod = method.MakeGenericMethod(value.GetType());
      var parameters = new object[] { value, 1 };
      return gmethod.Invoke(null, parameters);
  }

But on Invoke (using the same test instance), it says: System.NotSupportedException: 'Specified method is not supported.'

PS: I would like to avoid pointers and unsafe keyword.


Solution

  • You cannot access Span<T> using reflection because it cannot be boxed (to prevent stack references escaping).

    The only thing you can do is create a generic function that does all you want it to do, then call that using reflection.

    For example, you could return a byte[] array out of a generic function

    private static byte[] GetBytes(object value)
    {
        var method = typeof(ThisType).GetMethod("GetByteArray", BindingFlags.Static | BindingFlags.NonPublic);
        var gmethod = method.MakeGenericMethod(value.GetType());
        return (byte[])gmethod.Invoke(null, new object[] { value });
    }
    
    private static byte[] GetByteArray<T>(T value) where T : struct
    {
        return MemoryMarshal.AsBytes(MemoryMarshal.CreateSpan<T>(ref value, 1)).ToArray();
    }
    

    dotnetfiddle