I am trying create a delegate representation of constructor by emitting a Dynamic Method, which has to match this very "loosely-typed" signature so it can be used with any kind of parametrized constructor:
public delegate Object ParamsConstructorDelegate(params object[] parameters);
and the code for this creating the delegate looks like (note this is for Silverlight)
public static ParamsConstructorDelegate CreateDelegate(ConstructorInfo constructor)
{
Guard.ArgumentNotNull(constructor, "constructor");
Guard.ArgumentValue(constructor.GetParameters().Length == 0, MUSTBE_PARAMETERIZED_CONSTRUCTOR);
var _argumentTypes = new Type[] { typeof(object[]) };
var _parameters = constructor.GetParameters();
var _parameterTypes = _parameters.Select((p) => p.ParameterType).ToArray();
var _sourceType = constructor.DeclaringType;
var _method = new DynamicMethod(constructor.Name, _sourceType, _argumentTypes);
var _gen = _method.GetILGenerator();
for (var _i = 0; _i < _parameters.Length; _i++)
{
if (_parameters[_i].IsOut || _parameterTypes[_i].IsByRef)
{
if (_i < 128)
{
_gen.Emit(OpCodes.Ldarga_S, (byte)_i);
}
else
_gen.Emit(OpCodes.Ldarga, _i);
}
else
{
switch (_i)
{
case 0:
_gen.Emit(OpCodes.Ldarg_0, _i);
break;
case 1:
_gen.Emit(OpCodes.Ldarg_1, _i);
break;
case 2:
_gen.Emit(OpCodes.Ldarg_2, _i);
break;
case 3:
_gen.Emit(OpCodes.Ldarg_3, _i);
break;
default:
if (_i < 128)
_gen.Emit(OpCodes.Ldarg_S, (byte)_i);
else
_gen.Emit(OpCodes.Ldarg, _i);
break;
}
}
}
_gen.Emit(OpCodes.Newobj, constructor);
_gen.Emit(OpCodes.Ret); ;
return (ParamsConstructorDelegate)_method.CreateDelegate(typeof(ParamsConstructorDelegate));
}
Now, I'm getting a "Operation could destabilize the runtime." verification exception, obviously the IL is wrong, so I hoping someone could correct me.
Thanks
I can see two problems; firstly you don't need the
_i
for theLdarg_0
thruLdarg_3
cases (it is implicit). Secondly - your delegate only has one arg (the array). You're going to need to get the items out of the array and cast - something like below (which handles pass-by-value only; forref
/out
you'll have to define a local and use stloc / ldloca / etc):For info - I'm lazy - if I want to know what IL to write I write it in C# and then load it into reflector. For example, to do this I wrote a method:
and reversed it from there