如何创建从封闭泛型类型派生的动态类型

本文关键字:泛型类型 派生 类型 动态 何创建 创建 | 更新日期: 2023-09-27 18:14:04

我正在尝试动态地将任意数量的类型组合为继承所有这些类型的新类型。现在它应该只适用于接口。

我绝对知道有很多陷阱和严重的性能影响,但这只用于我的测试代码-更具体地说,用于创建多个接口的模拟。

所以,基本上我有一个类(TypeBuilder -见下面的代码),它能够创建这些类型。对于"简单"类型,它的效果非常好。但我也想传递闭泛型。当尝试使用我当前的实现时,当我试图创建动态类型(通过TypeBuilder.CreateType)时,会抛出TypeLoadException

我是否必须告诉TypeBuilder新类型是泛型类型,尽管它只派生自封闭泛型?如果是,我该怎么做?

我是这样使用的:

MultiTypeBuilder multiTypeBuilder = 
    new MultiTypeBuilder(Guid.NewGuid().ToString());   
multiTypeBuilder.SetBaseType(typeof(IFoo));
multiTypeBuilder.SetBaseType(typeof(IBar<IFoo>));
multiTypeBuilder.SetBaseType(typeof(IBaz));
Type multiType = multiTypeBuilder.CreateType();

这是我目前的实现(简化了一点):

private class MultiTypeBuilder
{
    private readonly TypeBuilder m_TypeBuilder;
    public MultiTypeBuilder(string name)
    {
        ModuleBuilder multiTypeModule = GetMultiTypeModule();
        TypeAttributes attributes = TypeAttributes.Interface | TypeAttributes.SpecialName | TypeAttributes.Abstract | TypeAttributes.Public;
        m_TypeBuilder = multiTypeModule.DefineType(name, attributes);
    }
    public void SetBaseType(Type baseType)
    {
        m_TypeBuilder.AddInterfaceImplementation(baseType);
    }
    public Type CreateType()
    {
        return m_TypeBuilder.CreateType();
    }
    private static ModuleBuilder GetMultiTypeModule()
    {
        AssemblyName assemblyName = new AssemblyName(c_DynamicAssemblyName);
        AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
        return assemblyBuilder.DefineDynamicModule("MultiTypeAssembly");
    }
}

感谢您的支持!

如何创建从封闭泛型类型派生的动态类型

您需要为接口定义(虚拟抽象)方法,因为您创建的是抽象类,而不是接口。几个问题:

  1. 当你枚举一个接口上的方法时,它将不包括来自继承接口的方法。为了找到你需要定义的所有方法,你必须递归地遍历继承的接口,加上它们继承的接口等等。

  2. 当你遍历接口时,你需要处理两个接口从同一个接口继承的情况,这样你就不会尝试创建两次方法。

  3. 如果您有两个接口包含具有相同签名的方法,则需要创建显式实现。它们不能是抽象的虚拟方法(至少如果你想遵循c#惯例的话),所以你需要发出一些IL代码来转发给其他虚拟的抽象方法。


实际上,我只是注意到你并没有在类型属性中指定它是一个Class。您需要包含TypeAttributes.Class或TypeAttributes.Interface。在后一种情况下,您不需要执行上述所有工作(如果我没记错的话,您也不需要Abstract)

真丢脸。

正如VirtualBlackFox所说,我的稍微浓缩的例子是有效的。在我的"实际"代码中,我通过组合需要组合的类型的FullNames来创建动态类型的名称。当与泛型类型一起使用时,这显然会产生无效的typename(我发现例如[是无效的,如果您考虑一下,这是有意义的)。

如果我从生成的类型名中删除任何非字母或数字字符,一切都像一个魅力。

谢谢你的回答/评论!