I try to create a dynamic method in .NET which has an "in" parameter, but it throws an exception in the EmitCall
line:
public struct Context
{
public string MyString { get; set; }
}
public interface IHandler<T>
{
void MyMethod(in Context context);
}
class MyMessage
{
}
class MyClass : IHandler<MyMessage>
{
public void MyMethod(in Context context)
{
}
}
class ContextMethodInvoker
{
private readonly InvokeHandler _invoker;
private delegate void InvokeHandler(object handler, in Context context);
public ContextMethodInvoker(MethodInfo methodInfo)
{
var dynamicMethod = new DynamicMethod(string.Empty,
typeof(void), new[] { typeof(object), typeof(Context).MakeByRefType() });
dynamicMethod.DefineParameter(1, ParameterAttributes.None, "handler");
dynamicMethod.DefineParameter(2, ParameterAttributes.In, "context");
var il = dynamicMethod.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.EmitCall(OpCodes.Callvirt, methodInfo, null);
il.Emit(OpCodes.Ret);
_invoker = (InvokeHandler)dynamicMethod.CreateDelegate(typeof(InvokeHandler));
}
public void Invoke(object handler, in Context context)
{
_invoker.Invoke(handler, in context);
}
}
And:
var messageHandlerType = typeof(IHandler<>);
var messageType = typeof(MyMessage);
var type = typeof(MyClass);
var interfaceType = messageHandlerType.MakeGenericType(messageType);
var contextMethod = new ContextMethodInvoker(
type.GetInterfaceMap(interfaceType).TargetMethods.SingleOrDefault()
);
var tm = new Context
{
MyString = "test"
};
contextMethod.Invoke(Activator.CreateInstance(type), tm);
What am I doing wrong? When I remove the "in" keywords and the MakeByRefType then it works.