Type.GetMethod alternative for TypeBuilder
Asked Answered
U

1

9

I'm making a .NET-compliant compiler using Reflection.Emit. The problem is, that although TypeBuilder is derived from Type, it does not let me use all the handy methods that Type provides.

The matters that really concern me are:

  1. Is there any way to get a list of methods, fields, properties, constructors etc. defined in a TypeBuilder, or I really have to make a TypeBuilderWrapper that keeps track of all those entities by myself? It has to store them somewhere inside, so there must be some way to extract them?

  2. The GetMethod method is very handy, because it can find the best fitting method override taking inheritance and generic covariance into account. Do I really have to reimplement it myself for the TypeBuilderWrapper?

The same issue probably applies to MethodBuilder, FieldBuilder etc. which, I believe, do not implement the lookup methods of MethodInfo and FieldInfo respectively.

Upshot answered 5/1, 2013 at 16:33 Comment(9)
This might not be the answer you are looking for. But have you looked into the DLR ( dlr.codeplex.com )?Bowse
@Bowse Could you explain how exactly would DLR help here?Samala
Can't you call CreateType() before trying to use GetMethod()? Also, could you explain why do you need overload resolution? When generating code, you usually already know which method you want to call.Samala
@svick, I've heard that you cannot add new entities once the TypeBuilder.CreateType() has been invoked, because it finalizes the type and loads in into memory. I haven't tested it myself though.Upshot
@svick, overload resolution is a must. Say, I have class A { } and class B : A { }. If my method has a signature of void test(A a), I must be able to call it passing an instance of class B.Upshot
@svick, DLR would help because DLR already figured out all this stuff for you since it is developed for people interested in creating their own language on top of the .NET CLRBowse
@Upshot You're saying that you have an instance of B and you know you want to call a method called "test". But couldn't you change your code so that you know you want to call void test(A a)? In other words, can you use the MethodInfo to call the method, instead of string?Samala
@svick, turning string into a MethodBuilder is mostly what making a compiler is all about! When I parse the input string containing the source code, I don't have MethodBuilders. I can only say that there's a method called test being invoked and something has been passed to it as a parameter, and it turns out to be an object of class B.Upshot
@rpgmaker, no, DLR is not applicable: it's suited for weakly typed languages, requires extra assemblies, and has a great overhead comparing to general code. Try compiling the code: ((dynamic)(new object())).ToString() and see for yourself in the Reflector.Upshot
S
9

TypeBuilder, MethodBuilder, etc are Type, MethodInfo, but they dont have all abilities of Type, MethodInfo until you call TypeBuilder.CreateType(). The reason TypeBuilder is derived from Type is it allows you you while building class A and B, you can reference they in both directions without finishing them. Let me give an example:

// sample.x
class A {
    void method1(B b) {}
}

class B {
    void method2(A a) {}
}

So the C# code to generate class A and B would be:

// ...
// define classes
TypeBuilder classA = moduleBuilder.DefineType("A");
TypeBuilder classB = moduleBuilder.DefineType("B");

// define class A's methods
MethodBuilder method1 = classA.defineMethod("method1", MethodAttributes.Public);
method1.SetParameters(classB);
// ... build method body

// define class B's methods
MethodBuilder method2 = classB.defineMethod("method2", MethodAttributes.Public);
method1.SetParameters(classA);
// ... build method body

// finish classes
classA.CreateType();
classB.CreateType();
// this time you can use GetMethod but you can not modify classes any more. 

Answer your questions, there are no ways to get list of methods, properties, etc in TypeBuilder until you call CreateType. But you should remember these methods, properties are created by your code, so you should know them all. If you want to create some class TypeBuilderWrapper, it's your choice. But from my opinion, you should do something like:

  • Write your own models (XClass, XMethod, XParam, etc) for you X language.
  • Turn your XParser to parse the X files into language model objects.
  • Do some analysis on created models to create links between your models. For example: in sample.x above, in B.method2, parameter A a should have a link to class A model.
  • using Reflection.Emit to create the target assembly. Remember the order is: define classes, define classes' methods, define classes methods' body, etc. Then call CreateType to finish then all. The order can be changed depends on your language design.

Those are all my idea, the code might not work. When I created my simple-stupid language, I created somethings like those. Hope I could help you.

Swanherd answered 10/3, 2013 at 7:36 Comment(1)
Yeah, in the out and out I was reduced to implementing those wrapper classes by hand, and it was pretty bothersome. Even more disappointing was the fact that TypeBuilder is sealed and you cannot create a simple derived class without breaking the interface. Thank you for your comment.Upshot

© 2022 - 2024 — McMap. All rights reserved.