【问题标题】:C# constructor to call constructor after executing codeC#构造函数在执行代码后调用构造函数
【发布时间】:2017-06-20 10:24:00
【问题描述】:

我已经看到有关构造函数链接的答案,但它们不适用于我的问题。

我有一个需要几个参数的以下构造函数:

public SerilogHelper(string conString, int minLevel)
    {
        var levelSwitch = new LoggingLevelSwitch();
        levelSwitch.MinimumLevel = (Serilog.Events.LogEventLevel)(Convert.ToInt32(minLevel));

        _logger = new LoggerConfiguration()
            .MinimumLevel.ControlledBy(levelSwitch)
            .WriteTo.MSSqlServer(connectionString: conString, 
                                 tableName: "Logs", 
                                 autoCreateSqlTable: true)
            .CreateLogger();
    }

这个构造函数的一个特定客户端没有参数所需的值,所以我希望能够调用这个简单的构造函数,它会获取所需的值,然后调用第一个构造函数:

public SerilogHelper()
    {
        string minLevel = SSOSettingsFileManager.SSOSettingsFileReader.ReadString(
          "LCC.Common", "serilog.level");
        string conString = SSOSettingsFileManager.SSOSettingsFileReader.ReadString(
          "LCC.Common", "serilog.connectionstring");

        SerilogHelper(conString, minLevel);
    }

问题是,我在调用第二个构造函数时得到一个红色波浪形消息 SerilogHelper is a 'type' but used like a 'variable'

【问题讨论】:

标签: c# constructor


【解决方案1】:

为什么不简单地添加这些参数?

// this assumes that SSOSettingsFileManager is static class
// this will automatically call these methods before passing 
// values to another ( non parameterless ) constructor
public SerilogHelper()
    : this ( 
        SSOSettingsFileManager.SSOSettingsFileReader.ReadString(
            "LCC.Common", "serilog.connectionstring"
        ),
        SSOSettingsFileManager.SSOSettingsFileReader.ReadString(
            "LCC.Common", "serilog.level"
        )
    )
{

}

// This will be called from default ( parameterless )
// constructor with values retrieved from methods
// called in previous constructor.
public SerilogHelper(string conString, int minLevel)
{
        var levelSwitch = new LoggingLevelSwitch();
        levelSwitch.MinimumLevel = (Serilog.Events.LogEventLevel)(Convert.ToInt32(minLevel));

        _logger = new LoggerConfiguration()
            .MinimumLevel.ControlledBy(levelSwitch)
            .WriteTo.MSSqlServer(connectionString: conString, 
                                 tableName: "Logs", 
                                 autoCreateSqlTable: true)
            .CreateLogger();
}

Test online

【讨论】:

    【解决方案2】:

    你不能那样做。您拥有它的最佳选择是将初始化代码移动到一个单独的方法中,您可以从两个构造函数中调用该方法。 允许的。

    public SerilogHelper()
    {
        string minLevel = SSOSettingsFileManager.SSOSettingsFileReader.ReadString(
          "LCC.Common", "serilog.level");
        string conString = SSOSettingsFileManager.SSOSettingsFileReader.ReadString(
          "LCC.Common", "serilog.connectionstring");
    
        this.Initialize(conString, minLevel);
    }
    
    public SerilogHelper(string conString, int minLevel)
    {
        this.Initialize(conString, minLevel);
    }
    
    protected void Initialize(string conString, int minLevel)
    {
        var levelSwitch = new LoggingLevelSwitch();
        levelSwitch.MinimumLevel = (Serilog.Events.LogEventLevel)(Convert.ToInt32(minLevel));
    
        _logger = new LoggerConfiguration()
            .MinimumLevel.ControlledBy(levelSwitch)
            .WriteTo.MSSqlServer(connectionString: conString, 
                                 tableName: "Logs", 
                                 autoCreateSqlTable: true)
            .CreateLogger();
    }
    

    【讨论】:

      【解决方案3】:

      我建议使用默认值

      public SerilogHelper(string conString = null, int minLevel = -1)
      {
          if (minLevel == -1)
            minLevel = SSOSettingsFileManager.SSOSettingsFileReader.ReadString(
            "LCC.Common", "serilog.level");
      
          if (conString == null)
            conString = SSOSettingsFileManager.SSOSettingsFileReader.ReadString(
            "LCC.Common", "serilog.connectionstring");
      
          var levelSwitch = new LoggingLevelSwitch();
          levelSwitch.MinimumLevel = (Serilog.Events.LogEventLevel)(Convert.ToInt32(minLevel));
      
          _logger = new LoggerConfiguration()
              .MinimumLevel.ControlledBy(levelSwitch)
              .WriteTo.MSSqlServer(connectionString: conString, 
                                   tableName: "Logs", 
                                   autoCreateSqlTable: true)
              .CreateLogger();
      }
      

      ....

      SerilogHelper myInstance = new SerilogHelper();
      

      编辑:我假设 minLevel = -1invalid 可以用作默认值,如果不是这种情况(任何 minLevel 值是允许的)int? 是一个可能的出路:

      public SerilogHelper(string conString = null, int? minLevel = null)
      {
          if (!minLevel.HasValue)
            minLevel = SSOSettingsFileManager.SSOSettingsFileReader.ReadString(
            "LCC.Common", "serilog.level");
      
          if (conString == null)
            conString = SSOSettingsFileManager.SSOSettingsFileReader.ReadString(
            "LCC.Common", "serilog.connectionstring");
      
          var levelSwitch = new LoggingLevelSwitch();
          levelSwitch.MinimumLevel = (Serilog.Events.LogEventLevel)(Convert.ToInt32(minLevel));
      
          _logger = new LoggerConfiguration()
              .MinimumLevel.ControlledBy(levelSwitch)
              .WriteTo.MSSqlServer(connectionString: conString, 
                                   tableName: "Logs", 
                                   autoCreateSqlTable: true)
              .CreateLogger();
      }
      

      【讨论】:

      • 只有当conString == nullminLevel == -1不是有效值时才能使用。
      • @Patrick Hofman:非常正确;如果任意minLevel被允许,那么int? minLevel = null是一个可能的出路。
      • 可选参数有很多陷阱。一个是“歧义”......给定“public Test() { Console.WriteLine("Default"); }”和“public Test(int i = 0) { Console.WriteLine("Optional"); }”,什么“新测试()”是否调用?另一个是默认值被“烘焙”到调用代码中。因此,如果更改默认值,则必须重新编译所有调用代码。例如如果 ProjectA 有一个带有可选参数的构造函数,并且 ProjectB 调用该构造函数,如果您重新编译 ProjectA 而不是 ProjectB,则 ProjectB 仍将使用旧的默认值调用构造函数。
      • @AndyJ:你说的很对,应该谨慎使用可选值;但是在这里,我们不会被反模式 1(我们想要的只是不提供连接字符串和级别的可能性)或反模式 2(我们没有将来想要更改的魔法值,但是 null-1null,如果允许任何级别))
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-18
      • 1970-01-01
      • 2021-07-19
      • 2021-11-23
      • 1970-01-01
      • 1970-01-01
      • 2013-01-11
      相关资源
      最近更新 更多