在非静态构造函数中设置静态字段 |为什么这行得通? | C#

Setting Static Field in Non-static Constructor | Why does this work? | C#

在此应用程序中,我们将 JUST.net 与自定义函数一起使用。 JUST.net 中的自定义函数必须是静态方法。我创建了一个定义所有静态函数的 class;这些函数通过反射注册到 JUST.net 上下文。我需要在这些静态函数中包含日志记录,以防其中一个映射失败。

为了完成这个,我们有这样的代码:

public class Transformations
{
  private static ILogger<Transformation> _logger;

  public Transformations(ILogger<Transformations> logger)
  {
     _logger = logger;
  }

  public static string MapAddress(string? streetNumber, string? streetName)
  {
    if(string.IsNullOrEmpty(streetNumber)
    { 
      _logger.LogError("The property was not provided.");
    }
    // etc...
  }
  // etc...
}

当我从测试中调用它时,如果我实例化 class 并静态引用函数,记录器就会工作。如果我不实例化 class 并静态引用方法,记录器将不起作用。

即:

  public class AddressUnitTest
  {
    private readonly Transformations _transformations;

    public AddressUnitTest()
    {
      var serilog = new LoggerConfiguration().WriteTo.Console().CreateLogger();
      var loggerFactory = new LoggerFactory().AddSerilog(serilog);
      var logger = loggerFactory.CreateLogger<Transformations>();
      _transformations = new Transformations(logger);
    }

    [Fact]
    public void Address(string? streetNumber, string? streetName)
    {
      var actualValue = Transformations.MapAddress(streetNumber, streetName);
      // etc...
    }
  }

鉴于您不能使用 _transformations.MapAddress() 并且必须静态引用这些方法,即:Transformation.MapAddress(),当我实例化一个看似无关的版本时,为什么记录器可以工作?

也就是说,为什么设置 _transformations = new Transformations(logger); 会授予 Transformations.MapAddress() 访问记录器的权限?

似乎有效;我只是不明白为什么。有没有更好的方法来完成这个?

原因是 _logger 字段唯一一次被初始化为任何东西是在 class 构造函数中。

最好编写一个静态方法来初始化记录器,并使您的整个 class 静态(这样它的所有成员都必须是静态的)这样就不会出现这种混淆:

public static class Transformations
{
  private static ILogger<Transformation> _logger;

  public static void InitialiseLogger(ILogger<Transformations> logger)
  {
     _logger = logger;
  }

  public static string MapAddress(string? streetNumber, string? streetName)
  {
    if(string.IsNullOrEmpty(streetNumber)
    { 
      _logger.LogError("The property was not provided.");
    }
    // etc...
  }
  // etc...
}

在您的单元测试中,应该可以有一个启动方法为所有单元测试调用一次 Transformations.InitialiseLogger(),这样您就不必在每个测试方法中重复它。 (或者其他方式——我不熟悉 xUnit 是如何做到这一点的。)