Using System.Reflection.Emit to create a call to "typeof()"

  • Thread starter Thread starter Mark Miller
  • Start date Start date
M

Mark Miller

I am using Reflection.Emit to dynamically build a class. A method of the
class to be built requires a Parameter of type "Type". But I don't know how
to use Emit to pass a call of "typeof()" to the method.

The method could look like this:

public void myDynamicMethod(Type type){
//.....do something with the Type passed in.......
}

the call to the method would look like this:

myDynamicMethod( typeof( myCustomType ) );

So essentially I am looking to use Emit to output the "typeof(
myCustomType )" part. Any suggestions would be appreciated.

Mark
 
Mark Miller said:
I am using Reflection.Emit to dynamically build a class. A method of the
class to be built requires a Parameter of type "Type". But I don't know
how
to use Emit to pass a call of "typeof()" to the method.

The method could look like this:

public void myDynamicMethod(Type type){
//.....do something with the Type passed in.......
}

the call to the method would look like this:

myDynamicMethod( typeof( myCustomType ) );

So essentially I am looking to use Emit to output the "typeof(
myCustomType )" part. Any suggestions would be appreciated.

If I understand you, you would emit a Ldtoken instruction and then call
Type::GetTypeFromHandle. The literal IL is:

ldtoken Test
call class [mscorlib]System.Type
[mscorlib]System.Type::GetTypeFromHandle(valuetype
[mscorlib]System.RuntimeTypeHandle)

There should be a overload for ILGenerator::Emit that takes a type as the
second parameter, which is what you would use to emit ldtoken.
 
Thanks, for the quick response. I'll try that right away.

Daniel O'Connell said:
Mark Miller said:
I am using Reflection.Emit to dynamically build a class. A method of the
class to be built requires a Parameter of type "Type". But I don't know
how
to use Emit to pass a call of "typeof()" to the method.

The method could look like this:

public void myDynamicMethod(Type type){
//.....do something with the Type passed in.......
}

the call to the method would look like this:

myDynamicMethod( typeof( myCustomType ) );

So essentially I am looking to use Emit to output the "typeof(
myCustomType )" part. Any suggestions would be appreciated.

If I understand you, you would emit a Ldtoken instruction and then call
Type::GetTypeFromHandle. The literal IL is:

ldtoken Test
call class [mscorlib]System.Type
[mscorlib]System.Type::GetTypeFromHandle(valuetype
[mscorlib]System.RuntimeTypeHandle)

There should be a overload for ILGenerator::Emit that takes a type as the
second parameter, which is what you would use to emit ldtoken.
 
I'm having trouble translating your il into Emit commands. I didn't say
before but I am new to the Reflection.Emit namespace and so if you could
interpret the IL for me I would appreciate it.

thanks,
Mark
 
Nevermind, it looks like a good nights sleep took care of everything. I had
been using Lutz Roeder's .Net Reflector and handn't been looking at IL to
view the results of my Emit code. I hand been looking at C# output. I
switched to IL mode and from what you said, I was able to compare the IL I
was trying to get against other code I had written, and that did it.

Since I wasn't able to find any other examples of this anywhere, here's the
solution:

I had actually been trying to call the protected base constructor from an
inherited class. The base constructor had a parameter that I wanted to hide
but I wanted to expose the other parameters in a public constructor. This is
what I wanted to see:

public myClass(string SomeParam) : base ( typeof( someClass ), SomeParam ){}

Here's the Emit code to achieve the result:

------------------------------ BEGIN
CODE -------------------------------------------
//build a constructor which passes an argument of type Type to base
constructor by calling typeof
ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Public,
CallingConventions.Standard, new Type[1]{typeof(string)});
ILGenerator ilGen = cb.GetILGenerator();

ilGen.Emit(OpCodes.Ldarg_0);
ilGen.Emit(OpCodes.Ldtoken, typeof(int));
ilGen.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", new
Type[1]{typeof(RuntimeTypeHandle)}));
ilGen.Emit(OpCodes.Ldarg_1);

//pass arguments to base class constructor
ilGen.Emit(OpCodes.Call,
typeof(myParent).GetConstructor(BindingFlags.Instance |
BindingFlags.NonPublic, null, new Type[2]{typeof(Type), typeof(string)},
null));

ilGen.Emit(OpCodes.Ret);
------------------------------ END
CODE -----------------------------------------------

Here's the IL (using Lutz Roeder's Reflector):

----------------------- BEGIN IL ----------------------------------------
..method public specialname rtspecialname instance void .ctor(string) cil
managed
{
// Code Size: 18 byte(s)
..maxstack 3
L_0000: ldarg.0
L_0001: ldtoken int32
L_0006: call [mscorlib]System.Type
[mscorlib]System.Type::GetTypeFromHandle([mscorlib]System.RuntimeTypeHandle)
L_000b: ldarg.1
L_000c: call instance void
[HelloWorld-Emit]HelloWorld_Emit.myParent::.ctor([mscorlib]System.Type,
string)
L_0011: ret

}
--------------------END IL -----------------------------------------------
 
Mark Miller said:
Nevermind, it looks like a good nights sleep took care of everything. I
had
been using Lutz Roeder's .Net Reflector and handn't been looking at IL to
view the results of my Emit code. I hand been looking at C# output. I
switched to IL mode and from what you said, I was able to compare the IL I
was trying to get against other code I had written, and that did it.

Good, looks correct to me. Sorry I didn't provide ILGenerator examples, but
itappears it didn't matter.
 
Mark,

The best way to solve this kind of problems is to code a sample class compile it and than use ILDASM or Reflector.NET to see the generated IL. (at least this is how i do it)

Pedro

**********************************************************************
Sent via Fuzzy Software @ http://www.fuzzysoftware.com/
Comprehensive, categorised, searchable collection of links to ASP & ASP.NET resources...
 
Back
Top