Turing a TypeReference into a .NET Type

644 views
Skip to first unread message

JasonBock

unread,
Nov 4, 2008, 7:22:48 PM11/4/08
to mono-cecil
I have a TypeReference. I want to turn it into a .NET Type (i.e
System.Type in mscorlib). Is there a way to do this in the API, either
directly or indirectly?

Thanks,
Jason

Jb Evain

unread,
Nov 5, 2008, 2:57:09 PM11/5/08
to mono-...@googlegroups.com
Hey,

There's no such API I'm aware of. To be honest it's the first time
I've been asked for that.

A simple way to do that would be by resolving types by names. Note
that Cecil uses the CIL naming conventions, while System.Reflection
has a custom naming scheme for nested types and generic definitions.

--
Jb Evain <j...@nurv.fr>

JasonBock

unread,
Nov 6, 2008, 9:13:21 AM11/6/08
to mono-cecil
Here's the scenario that I'm trying to solve - maybe there's an
alternative way to do this that doesn't require a TypeReference ->
Type conversion.

I'm trying to output the values from the public instance properties on
a given type. I have the type of the property from the PropertyType
property, and it's a TypeReference. Now, I want to add this value to a
StringBuilder via its Append() method. Append() has numerous overloads
and I'd like to call the version that has the "best match" - i.e. if
the property type is int, I want to call Append(int), if it's a
string, I want to call Append(string).

So...I want to get the right append method by doing something like
this:

var append =
@this.Module.Import(typeof(StringBuilder).GetMethod("Append",
new Type[] { typeof(object) }));

The problem that you can see if that I want to use the TypeReference -
something like this:

var append =
@this.Module.Import(typeof(StringBuilder).GetMethod("Append",
new Type[] { ConvertToType(property.PropertyType) }));

where ConvertToType() is a mythical function that does the
TypeReference -> Type conversion.

The other alternative would be to get the method completely from the
Cecil API - i.e. get a TypeReference to StringBuilder, walk through
its methods in the Methods collection, and find the right match. Do
you think that would be a better option?

As a side note, it would be nice if the Cecil API has more GetXXX()
methods like the Reflection API does. Would make it a lot easier to
discover members.

Regards,
Jason

jonp

unread,
Nov 10, 2008, 9:36:13 AM11/10/08
to mono-cecil
On Nov 6, 9:13 am, JasonBock <ja...@jasonbock.net> wrote:
> Here's the scenario that I'm trying to solve - maybe there's an
> alternative way to do this that doesn't require a TypeReference ->
> Type conversion.
>
> I'm trying to output the values from the public instance properties on
> a given type. I have the type of the property from the PropertyType
> property, and it's a TypeReference. Now, I want to add this value to a
> StringBuilder via its Append() method. Append() has numerous overloads
> and I'd like to call the version that has the "best match" - i.e. if
> the property type is int, I want to call Append(int), if it's a
> string, I want to call Append(string).

I don't understand why you'd want this behavior, especially
considering that Mono's StringBuilder.Append(int) method is:

public StringBuilder Append (int value) {
return Append (value.ToString());
}

i.e. it just calls .ToString() on the value, and it does this for all
of the StringBuilder.Append(TArg) (i.e. single-argument) methods
except for StringBuilder.Append(char[]), StringBuilder.Append(string),
and StringBuilder.Append(char).

So I don't see much need for looking up the "appropriate"
StringBuilder.Append() method via Reflection for later invocation,
since for most cases it'll be equivalent to just calling
StringBuilder.Append(object) (which calls .ToString() on the argument
after checking for null).

Now that said I *can* think of a need for loading up the matching
System.Type for the TypeReference: so that object.ToString() will work
"properly" (for varying definitions of "properly"). For example, if
you have:

// use an enum from mscorlib.dll
public const System.AttributeTargets = System.AttributeTargets.All;

When you grab the FieldDefinition.Constant property, you'll get 32767
(an int) instead of System.AttributeTargets.All (the enum value).
This is because you need the relevant System.Type loaded (e.g.
typeof(System.AttributeTargets)), and the object you care about within
a System.AttributeTargets variable, for .ToString() to Do The Right
Thing.

Similar examples are if you have a property/field of a custom type for
which you override object.ToString() -- your overridden
object.ToString() won't be invoked if you call
FieldDefinition.Constant.ToString(), as the relevant Type hasn't been
loaded.

This is technically a feature as it means the Assembly doesn't need to
be loaded into the AppDomain, but it can be annoying...

- Jon
Reply all
Reply to author
Forward
0 new messages