使用动态类型作为它自己的基类型的参数
本文关键字:类型 基类 自己的 参数 它自己 动态 | 更新日期: 2023-09-27 18:05:02
我正在尝试编写一些代码,在运行时生成类型。我有一个需要实现的接口,但是这个约束给我带来了一些困难。
正如在评论中所指出的,接口看起来像和无穷递归,但不是。它编译得很好
界面类似于:
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>
也可以做得很好
使用基类型而不是接口的答案也是有效的(如标题所示)。例如
TypeBuilder tb = mb.DefineType(
"typename",
TypeAttributes.Public,...,null);
, . .为SomeType<T>
, T为定义的类型
举个例子,当用代码编写时可以是:
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(){}
}
这段代码确实可以编译
您只需要在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)