7
[Name("Admin")]
public class TestAdmin : TestUserBase<TestAdmin>
{
    public TestAdmin(Type webDriverType) : base(webDriverType)
    {
    }
}

Currently, I have a bunch of classes of this form that I'd like to create at runtime using Reflection.Emit. However, I'm running into an issue when I attempt to add the parent - since the TestAdmin class doesn't exist before runtime, I don't know how to create

TestUserBase<TestAdmin>

Any ideas?

svick
  • 236,525
  • 50
  • 385
  • 514
Matt Koster
  • 219
  • 1
  • 2
  • 8
  • Are you having trouble specifically because the argument to the base generic class is *this* class? – Michael Gunter Jun 10 '13 at 21:18
  • I believe you have a chicken and egg problem... The C# compiler may be able do this because it's probably not using Reflection.Emit to generate the IL. I'm not sure if there is a solution to this problem... – Brandon Cuff Jun 10 '13 at 21:26
  • Does make-generic-method accept the type-builder? Actually, though, I do seem to recall some thorny chicken/egg areas that il-emit struggles with. Lately I'm using IKVM-reflection which has the same api as reflection-emit but which fixes a lot of these areas – Marc Gravell Jun 10 '13 at 21:49
  • @MarcGravell Lee's code works for me, I think this isn't one of the problematic cases. – svick Jun 11 '13 at 11:38
  • @MichaelGunter Yes, that's been my issue. I think Lee's code will work, but haven't had a chance to test it yet. – Matt Koster Jun 11 '13 at 13:10

2 Answers2

7

You can set the parent type using SetParent:

TypeBuilder tb = mb.DefineType("TestAdmin", TypeAttributes.Public);
tb.SetParent(typeof(TestUserBase<>).MakeGenericType(tb));

Type theType = tb.CreateType();
svick
  • 236,525
  • 50
  • 385
  • 514
Lee
  • 142,018
  • 20
  • 234
  • 287
3

OK. I haven't been able to test this thoroughly, but I think this is possible. Try something like this:

Assuming your generic base class is already defined (i.e., you're not generating TestUserBase<T>), you should be able to do something like this:

var emittedType = module.DefineType("TestAdmin", TypeAttributes.Public | TypeAttributes.Class);
var baseType = typeof(TestUserBase<>).MakeGenericType(type);
emittedType.SetParent(baseType);

Of course, if TestUserBase<T> is begin generated, you can use this same logic using MakeGenericType on the dynamic type TestUserBase<T>. The SetParent logic is the same.

Michael Gunter
  • 12,528
  • 1
  • 24
  • 58