3

I'm trying to write some code generating a type at runtime. I have an interface I need to implement but the constraint is causing me some difficulties.

As has been noted in the comments, yes the interface looks like and endless recursion but is not. It compiles just fine

The interface looks similar to:

interface IFoo<T> where T : IFoo<T>{ T MyProperty{get;} } 

When I the try to define my dynamic type using ModuleBuilder I have an issue:

TypeBuilder tb = mb.DefineType( "typename", TypeAttributes.Public,typeof(object),new[]{...}); 

have do I get to pass in a IFoo where T is the type I'm trying to define?

The code above in C# but answers in F# that let's me dynamically construct class SomeType : IFoo<SomeType> will do just fine as well

Answer that uses a base type instead of an interface is also valid (as the title suggests). I.e.

 TypeBuilder tb = mb.DefineType( "typename", TypeAttributes.Public,...,null); 

where .. is of SomeType<T> and T is the type being defined

EDIT: As an example of this when written in code could be:

 public interface ISelf<T> where T : ISelf<T> { T Prop { get; } } public class SelfBase<T> : ISelf<T> where T : SelfBase<T>{ public T Prop { get { return (T)this; } } } public class FooBar : SelfBase<FooBar>{ public void Bar(){ Prop.NonInterfaceMethod(); } public void NonInterfaceMethod(){} } 

That piece of code does indeed compile.

5
  • 1
    Does this even work? This interface definition looks like an endless recursion to me... Commented Aug 9, 2011 at 10:45
  • Your interface looks very strange. T is an IFoo<T>, where again T is an IFoo<T>, and so on. This looks as if it will produce some sort of overflow because you cannot specify T. Keyword: recursion Commented Aug 9, 2011 at 10:47
  • @Daniel it does indeed work. I started out compiling a static version before I tryed the dynamic. Commented Aug 9, 2011 at 10:47
  • @Christian see it as a version of en.wikipedia.org/wiki/Curiously_recurring_template_pattern. It does indeed compile Commented Aug 9, 2011 at 10:50
  • I would say it is not possible with the ModuleBuilder and TypeBuilder classes as their API needs a Type for the interface to implement and you don't have one until you call CreateType on the type builder at which point it is too late... Commented Aug 9, 2011 at 11:25

1 Answer 1

2

You just need to use the SetParent method on the TypeBuilder. Here's how to do it in F#:

open System open System.Reflection open System.Reflection.Emit type SelfBase<'t when 't :> SelfBase<'t>> = member x.Prop = x :?> 't type Foo = class inherit SelfBase<Foo> end let ab = AppDomain.CurrentDomain.DefineDynamicAssembly(AssemblyName("test"), AssemblyBuilderAccess.Run) let mb = ab.DefineDynamicModule("test") let tb = mb.DefineType("typename", TypeAttributes.Public) tb.SetParent(typedefof<SelfBase<Foo>>.MakeGenericType(tb)) let ty = tb.CreateType() // show that it works: let instance = System.Activator.CreateInstance(ty) let prop = instance.GetType().GetProperties().[0].GetValue(instance, null) let same = (prop = instance) 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.