当前位置:主页 > 软件编程 > .NET代码 >

c# 9.0新特性――模块初始化器

时间:2021-11-06 10:10:10 | 栏目:.NET代码 | 点击:

作者:MarkKang
出处:https://www.cnblogs.com/markkang/

1 背景动机

关于模块或者程序集初始化工作一直是C#的一个痛点,微软内部外部都有大量的报告反应很多客户一直被这个问题困扰,这还不算没有统计上的客户。那么解决这个问题,还有基于什么样的考虑呢?

2 详细设计

C# 9.0将模块初始化器设计为一个Attribute,用这个Attribute来修饰进行模块初始化逻辑的方法,就实现了模块初始化功能。这个Attribute被命名为ModuleInitializerAttribute,具体定义如下:

using System;
namespace System.Runtime.CompilerServices
{
  [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
  public sealed class ModuleInitializerAttribute : Attribute { }
}

如果要使用模块初始化器,你只要将ModuleInitializerAttribute用在符合下面要求的方法上就可以了。

  1. 该方法必须使静态的、无参的、返回值为void的函数。
  2. 该方法不能是泛型或者包含在泛型类型里
  3. 该方法必须是可从其所在模块里访问的。也就是说,方法的有效访问符必须是internal或者public,不能是局部方法。
using System.Runtime.CompilerServices;
class MyClass
{
  [ModuleInitializer]
  internal static void Initializer()
  {
    // ...
  }
}

被修饰为ModuleInitializerAttribute的静态方法会被编译器在编译时,在全局的静态构造函数中生成此代码调用。如果有多个被修饰为初始化器的函数,则每个函数生成一个初始化器代码调用,这些初始化器代码调用代码会按照一定的顺序(类型名称顺序和代码顺序)生成。当模块在被加载时,全局静态构造函数开始执行,从而完成模块代码初始化工作。

3 问题与最佳实践

模块初始化器与静态构造函数之间有着一定的关联影响。因为模块初始化器是一个静态方法,因而其被调用执行前,必然会引起其所处类型的静态构造函数的执行。请参考下列示例:

static class ModuleInit
{
  static ModuleInit()
  {
    //先执行
    Console.WriteLine("ModuleInit静态构造函数 cctor");
  }

  [ModuleInitializer]
  internal static void Initializer()
  {
    //在静态构造函数执行后才执行
    Console.WriteLine("模块初始化器");
  }
}

在一个模块中指定多个模块初始化器的时候,他们之间的顺序也是一个值得注意的问题。以上这些问题的存在,就要求我们注意以下几点:

在指定了模块初始化器的类型中,不要在静态构造函数中,写与模块初始化器中代码有着顺序依赖代码,最好的就是不要使用静态构造函数。

多个模块初始化器之间的代码,也不要有任何依赖关系,保持各个初始化器代码的独立性。

4 结束语

日常开发中,我们通常需要在模块初始化的时候,做一些前置性的准备工作,以前常采用静态构造函数这种不具有全局性方法,局限性很大,现在,这些都得到了完美解决。

您可能感兴趣的文章:

相关文章