Hi,

I've had the same issue before, but I've managed to solve it with the help
of Jb.

What you need to do is the following:

TypeReference genericArg = _moduleDefinition.TypeSystem.Int32;
GenericInstanceType genericType =
_moduleDefinition.Import(typeof(Nullable<>))
.MakeGenericInstanceType(genericArg);
MethodDefinition ctor = genericType.Resolve().Methods.First(m =>
m.IsConstructor && m.Parameters.Count == 1);

Note that if you try to emit a newobj instruction with 'ctor' with its
operand at this point, you'll get invalid IL, because when you use
Resolve(), you lose all generic argument information. We need to provide
that manually.
For that, you have to add your generic argument to ctor.DeclaringType, or
alternatively, you can use Rocks' MakeGenericInstanceType, like so:

ctor.DeclaringType = ctor.DeclaringType.MakeGenericInstanceType(genericArg);

Now you can emit your newobj instruction with 'ctor' being its argument.
Note that you _might_ need to clone ctor.DeclaringType first (I'm not sure,
I don't have my code in front of me atm), but you get the general idea.

Hope this helps!

2011/5/8 seesharper <[email protected]>

> Hi!
>
> I don't understand how to emit the code to create an instance of a
> generic type.
>
> Mono.Cecil 0.9.4.0
>
>
> I will illustrate this with a very simple example.
>
> This is the code that I want to emit.
>
>       public void TestNull(int value)
>        {
>            Nullable<int> test = value;
>        }
>
> NOTE:
>
> I don't know that the generic argument is an int at the time of
> emitting the code.
>
> I need to read the parameter type and create a Nullable<T> according
> to the parameter type.
>
> This means that I CAN'T do something like:
>
> MethodReference ctor = _moduleDefinition.Import(typeof
> (Nullable<int>).GetConstructor(new Type[] {typeof (int)}));
>
>
> This is the IL code that needs to be emitted.
>
>    .maxstack 2
>    .locals init (
>        [0] valuetype [mscorlib]System.Nullable`1<int32> test)
>    L_0000: nop
>    L_0001: ldloca.s test
>    L_0003: ldarg.1
>    L_0004: call instance void
> [mscorlib]System.Nullable`1<int32>::.ctor(!0)
>    L_0009: nop
>    L_000a: ret
>
>
> So this is what I got so far.
>
> First a create a GenericInstanceType:
>
> var nullableType = _moduleDefinition.Import(typeof(Nullable<>));
> var genericType =
>
> nullableType.MakeGenericInstanceType(_moduleDefinition.Import(typeof(int)));
>
> (yeah, I used the Cecil.Rocks extension method for creating the
> generic instance type, but that is not the issue here.)
>
> The int would be the type from the value parameter of the TestNull
> method.
>
> Now I have a GenericInstanceType that represents Nullable<int>.
>
> But how do I create a MethodReference that represents the constructor
> passed to OpCodes.NewObj?
>
> The GenericInstanceType which is derived from MethodReference does not
> have a collection of methods so I can't get it from there either.
>
> Next I tried something like this:
>
> MethodReference constructorReference = new MethodReference(".ctor",
> _moduleDefinition.Import(typeof(void)), genericType);
>
> No luck on this either.
>
> A lot of forum posts suggests that the methodreference should be added
> to the MemberReferences collection of the module.
>
> But that is a read-only collection available from the
> GetMemberReferences method.
>
>
>
> I must be missing something?
>
> Any help on this issue would be great!!!
>
> Regards
>
> Bernhard Richter
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> --
> --
> mono-cecil

-- 
--
mono-cecil

Reply via email to