如何在生成的动态类型上抑制默认构造函数

How to suppress default constructor on a generated dynamic type

在 .NET 中创建动态类型时,会生成默认构造函数。我该如何抑制它?

var typeBuilder = moduleBuilder.DefineType(
    type.FullName,
    TypeAttributes.NotPublic | TypeAttributes.BeforeFieldInit);

这记录在 TypeBuilder.DefineConstructor Method 的 "Remarks Section" 中。

If you do not define a constructor for your dynamic type, a default constructor is provided automatically, and it calls the default constructor of the base class.

If you define a constructor for your dynamic type, a default constructor is not provided. You have the following options for providing a default constructor in addition to the constructor you defined:

  • If you want a default constructor that simply calls the default constructor of the base class, you can use the DefineDefaultConstructor method to create one (and optionally restrict access to it). Do not provide an implementation for this default constructor. If you do, an exception is thrown when you try to use the constructor. No exception is thrown when the CreateType method is called.

  • If you want a default constructor that does something more than simply calling the default constructor of the base class, or that calls another constructor of the base class, or that does something else entirely, you must use the TypeBuilder.DefineConstructor method to create one, and provide your own implementation.

此行为与定义 class 而不显式定义默认构造函数没有什么不同;编译器生成一个 public 默认构造函数来调用基本构造函数。

如果你想要一个私有的默认构造函数,那么:

 ConstructorBuilder ctor = typeBuilder.DefineDefaultConstructor(MethodAttributes.Private);

编辑:

评论中提到staticclass没有构造函数。在与 Reflector 来回交流之后,我确定以下内容将创建一个静态动态 class,它具有由 c# 生成的相同默认属性。

public void Test()
{
AssemblyName asmName = new AssemblyName("TestAsmStatic");
AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);
ModuleBuilder mb = ab.DefineDynamicModule(asmName.Name, asmName.Name + ".dll");
TypeBuilder tb = mb.DefineType("StaticType", TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit | TypeAttributes.Abstract);
Type t = tb.CreateType();
ab.Save(asmName.Name + ".dll");

ConstructorInfo[] ci = t.GetConstructors((System.Reflection.BindingFlags)(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static));
Console.WriteLine(ci.Length.ToString());
}