используя динамический тип в качестве аргумента своего собственного базового типа - PullRequest
3 голосов
/ 09 августа 2011

Я пытаюсь написать код, генерирующий тип во время выполнения. У меня есть интерфейс, который мне нужно реализовать, но ограничение вызывает у меня некоторые трудности.

Как было отмечено в комментариях, да интерфейс выглядит как как бесконечная рекурсия, но это не так. Компилируется просто отлично

Интерфейс выглядит примерно так:

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

Когда я пытаюсь определить мой динамический тип с помощью ModuleBuilder, у меня возникает проблема:

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

Должен ли я передать IFoo, где T - это тип, который я пытаюсь определить?

Код выше в C #, но отвечает на F #, что давайте мне динамически построить class SomeType : IFoo<SomeType> тоже будет хорошо

Ответ, который использует базовый тип вместо интерфейса, также действителен (как предполагает заголовок). * 1018 Т.е. *

 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 Ответ

2 голосов
/ 09 августа 2011

Вам просто нужно использовать метод SetParent на TypeBuilder.Вот как это сделать в 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)
...