在 C# 中是否可以在运行时创建一个类型,该类型继承自泛型类,其中基类的模板参数是正在构造的当前类?这将编译正常:
// I have this class:
public class OtherClass<T>
where T : OtherClass<T>
{ }
// I want to create this at runtime:
public class MyClass : OtherClass<MyClass>
{ }
但我不确定如何使用 System.Reflection.Emit.ModuleBuilder.TypeBuilder
创建 MyClass
:
AssemblyName asn = new AssemblyName("test.dll");
AssemblyBuilder asb = AppDomain.CurrentDomain.DefineDynamicAssembly(
asn, AssemblyBuilderAccess.RunAndSave, @"D:\test_assemblies");
ModuleBuilder = modb = asb.DefineDynamicModule("test", "test.dll");
TypeBuilder tb = modb.DefineType(
"test",
TypeAttributes.Public | TypeAttributes.Class,
typeof(MyClass)); // How to specify inheritance?
// populate properties, fields, methods, etc., emit...
tb.CreateType();
这可能吗?
编辑 - 根据目前的回复,我试过这个:
public class OtherClass<T>
where T : OtherClass<T>
{ }
public static void CreateSimple()
{
AssemblyName asn = new AssemblyName("test");
AssemblyBuilder asb = AppDomain.CurrentDomain.DefineDynamicAssembly(
asn, AssemblyBuilderAccess.RunAndSave, @"D:\test_asms");
ModuleBuilder modb = asb.DefineDynamicModule("test", "test.dll");
try
{
TypeBuilder tb = modb.DefineType(
"MyClass",
TypeAttributes.Public | TypeAttributes.Class);
Type my = tb.CreateType();
tb.SetParent(typeof(OtherClass<>).MakeGenericType(my));
my = tb.CreateType();
}
catch (Exception e)
{
throw;
}
}
但是得到这个异常:
GenericArguments[0], 'MyClass', on 'MyProject.Factory+OtherClass`1[T]'
violates the constraint of type 'T'.
最佳答案
编辑:这是我最终的工作答案:
AssemblyName asn = new AssemblyName("test.dll");
AssemblyBuilder asb = AppDomain.CurrentDomain.DefineDynamicAssembly(
asn, AssemblyBuilderAccess.RunAndSave, @"D:\test_assemblies");
ModuleBuilder modb = asb.DefineDynamicModule("test", "test.dll");
TypeBuilder tb = modb.DefineType(
"test",
TypeAttributes.Public | TypeAttributes.Class);
// Typebuilder is a sub class of Type
tb.SetParent(typeof(OtherClass<>).MakeGenericType(tb));
var t2 = tb.CreateType();
var i = Activator.CreateInstance(t2);
诀窍是使用参数化泛型调用 SetParent,参数是正在构造的类型本身的类型构建器。
使用 TypeBuilder.SetParent(Type parent)方法。
使用时要小心,异常抛出延迟到CreateType
打电话:
If parent is null, Object is used as the base type.
In the .NET Framework versions 1.0 and 1.1, no exception is thrown if parent is an interface type, but a TypeLoadException is thrown when the CreateType method is called.
The SetParent method does not check for most invalid parent types. For example, it does not reject a parent type that has no default constructor when the current type has a default constructor, it does not reject sealed types, and it does not reject the Delegate type. In all these cases, exceptions are thrown by the CreateType method.
构建通用类型 OtherClass<T>
, 使用 MakeGenericType方法:
var genericType = typeof(OtherClass<>).MakeGenericType(typeof(MyClass));
关于c# - 在运行时创建类型 "MyClass : OtherClass<MyClass> { }"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13276447/