Since your struct would naturally be a ref struct which will live on the stack (and can't escape to the managed heap), you face several compiler limitations and have a few hurdles to overcome.
- A ref struct can't be the element type of an array.
- A ref struct can't be a declared type of a field of a class or a non-ref struct.
- A ref struct can't implement interfaces.
- A ref struct can't be boxed to System.ValueType or System.Object.
- A ref struct can't be a type argument. vA ref struct variable can't be captured by a lambda expression or a local function.
- A ref struct variable can't be used in an async method. However, you can use ref struct variables in synchronous methods, for example, in
those that return Task or Task.
- A ref struct variable can't be used in iterators.
As you can see, ref struct can't be boxed on the heap. This means you will not be able to cast to an object and use Invoke. However you can use an expression tree or relection.emit
When using an expression tree you will need to use a delegate with Expression.Lambda as ref struct can't be used as type parameters in a Func.
Given
public readonly ref struct Bob
{
public Bob(ReadOnlySpan<byte> myProperty)
=> MyProperty = myProperty;
public ReadOnlySpan<byte> MyProperty { get; }
}
...
public static byte DoSomething(Bob bob)
=> bob.MyProperty[1]; // return something from the span ¯\_(ツ)_/¯
delegate byte myDelegate(Bob asd);
...
var bytes = new byte[] {1, 2, 3};
var span = bytes.AsSpan();
var bob = new Bob(span);
Usage
var method = typeof(SomeType).GetMethod("DoSomething");
var parameter = Expression.Parameter(typeof(Bob), "b");
var call = Expression.Call(method, parameter);
var expression = Expression.Lambda<myDelegate>(call, parameter);
var func = expression.Compile();
var result = func(bob);
Console.WriteLine(result);
Results
2
Or with the in parameter modifier you'll need to make use of MakeByRefType
Returns a Type object that represents the current type when passed as
a ref parameter
public static byte DoSomething(in Bob bob)
=> bob.MyProperty[1]; // return something from the span ¯\_(ツ)_/¯
delegate byte myDelegate(in Bob asd);
...
var method = typeof(SomeType).GetMethod("DoSomething", new[] {typeof(Bob).MakeByRefType()});
var parameter = Expression.Parameter(typeof(Bob).MakeByRefType(), "b");
var call = Expression.Call(method, parameter);
var expression = Expression.Lambda<myDelegate>(call, parameter);
var func = expression.Compile();
var result = func(bob);
Note : This code is not the bastion perfect expression'ing, however it should work. Also this is built for a static method, you will need to pass in an instance if it's not