2011-08-09 2 views
3

런타임에 유형을 생성하는 코드를 작성하려고합니다. 구현해야 할 인터페이스가 있지만 제약으로 인해 어려움이 있습니다.동적 유형을 자체 basetype에 대한 인수로 사용

주석에서 언급했듯이 인터페이스 예 : 처럼 보이지만 끝없는 재귀를 나타내지 만 그렇지 않습니다.

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

가지고 내가 전달받을 수 있나요 : 나는 시도 내가 문제가있는 ModuleBuilder를 사용하여 내 동적 유형을 정의 할 때

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

: 그것은

인터페이스는 비슷합니다 잘 컴파일 IFoo에서 T는 내가 정의하려고하는 타입인가?

나 동적 class SomeType : IFoo<SomeType>가 잘뿐만 아니라 인터페이스 대신 기본 형식을 사용

대답을 할 것입니다 구축하자 C#을하지만 F 번호에 대한 답변에서 위의 코드는 (제목에서 알 수 있듯이)도 유효합니다. 나는.

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

여기서 ..는 SomeType<T>이며 T는 정의되는 유형

EDIT이의 예로서 될 수있는 코드로 작성된 :

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(){} 
    } 

조각 즉 코드가 실제로 컴파일됩니다.

+1

이 방법이 효과가 있습니까? 이 인터페이스 정의는 저에게 끝없는 재귀처럼 보입니다 ... –

+0

인터페이스가 매우 이상하게 보입니다. T는 IFoo 이고, 다시 T는 IFoo 입니다. 이것은 T를 지정할 수 없기 때문에 오버 플로우가 발생하는 것처럼 보입니다. 키워드 : recursion – Christian

+0

@Daniel 실제로 작동합니다. 나는 동적 인 것을 시도하기 전에 정적 버전을 컴파일하기 시작했다. –

답변

2

TypeBuilder에서 SetParent 메서드를 사용해야합니다. 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) 
+0

Excellent thanks –