Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在.Net Core 2.2类库项目中未读取/检测到App.config值_C#_Asp.net Core_.net Core_.net Core 2.2 - Fatal编程技术网

C# 在.Net Core 2.2类库项目中未读取/检测到App.config值

C# 在.Net Core 2.2类库项目中未读取/检测到App.config值,c#,asp.net-core,.net-core,.net-core-2.2,C#,Asp.net Core,.net Core,.net Core 2.2,我正在.net core 2.2中创建类库项目,该项目可用于.net core和.net framework 因为它是类库项目,所以我添加了app.config来读取配置值。已从Nuget软件包安装ConfigurationManager。下面是app.config文件 <?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="InputKe

我正在.net core 2.2中创建类库项目,该项目可用于.net core和.net framework

因为它是类库项目,所以我添加了app.config来读取配置值。已从Nuget软件包安装ConfigurationManager。下面是app.config文件

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="InputKey" value="12345" />
  </appSettings>
</configuration>
添加了Nunit测试项目,并在其中添加了app.config。该项目已成功构建。当我调试我的测试用例时,下面的行总是返回null

  • 尝试为app.config(类库和测试项目)始终复制,并将Nunit测试项目设置为启动项目-不工作
  • 已从类库项目中删除app.config[![enter image description here][1][1],并仅保留测试项目app.config-不工作
  • 将类库设置为启动项目-不工作
  • 你可以查看我的帖子

    旁注:这种方法适用于json文件

    首先安装这2个软件包

    Install-Package Microsoft.Extensions.Options
    Install-Package Microsoft.Extensions.DependencyInjection
    
    在代码中

    public static void Main()
    {
        var serviceCollection = new ServiceCollection();
        ConfigureServices(serviceCollection);
    }
    
    private static void ConfigureServices(IServiceCollection serviceCollection)
    {
          var currentDir = ProjectPath.GetApplicationRoot();
    
         // build configuration
         varconfiguration = newConfigurationBuilder()
                   .SetBasePath(currentDir)
                   .AddJsonFile("appsettings.json",false)
                   .Build();
    
         serviceCollection.AddOptions();
         serviceCollection.Configure<WebJobSettings>(configuration.GetSection("WebJobSettings"));
         // add app
         serviceCollection.AddTransient<WebJob>();
    }
    
    publicstaticvoidmain()
    {
    var servicecolection=新servicecolection();
    配置服务(serviceCollection);
    }
    专用静态void配置服务(IServiceCollection serviceCollection)
    {
    var currentDir=ProjectPath.GetApplicationRoot();
    //构建配置
    varconfiguration=newConfigurationBuilder()
    .SetBasePath(当前目录)
    .AddJsonFile(“appsettings.json”,false)
    .Build();
    serviceCollection.AddOptions();
    Configure(configuration.GetSection(“WebJobSettings”);
    //添加应用程序
    serviceCollection.AddTransient();
    }
    
    那就这样读吧

    public class WebJob
    {
      private readonly IOptions<WebJobSettings> _webJobSettings;
      public WebJob(
        IOptions<WebJobSettings> webJobSettings)
      {
        _webJobSettings = webJobSettings;
      } 
    }
    
    公共类WebJob
    {
    私有只读IOPS\u webJobSettings;
    公共网络作业(
    IOptions(网络作业设置)
    {
    _webJobSettings=webJobSettings;
    } 
    }
    
    首先不要让配置文件进入单元测试!改为使用模拟来传递配置值。这有几个优点:

    • 您将能够测试不同的配置值集,而不仅仅是当前配置文件中的配置值集
    • 您将能够针对无效输入测试配置值
    • 您不必记住始终维护配置文件的另一个工作副本
    • 更干净的体系结构:一般来说,单元测试不应该接触物理文件,而应该只测试类的行为
    下面的代码是关于如何使用模拟为单元测试提供配置值的建议:

    // The class that is accessed in order to get some config setting
    public class AppConfig
    {
        // The provider reads from a physical file when your lib is shipped but in your tests it will be mocked 
        private readonly AppConfigProvider provider;
    
        // Constructor used by your app or library
        public AppConfig() : this(new AppConfigProvider())
        {
        }
    
        // Constructor that can be used by your unit testing framework to inject a mock
        internal AppConfig(AppConfigProvider provider)
        {
            this.provider = provider;
        }
    
        public string InputKey => GetConfigValueOrThrow("InputKey");
    
        private string GetConfigValueOrThrow(string configKey)
        {
            string value = provider.GetSetting(configKey);
    
            if (value == null)
                throw new Exception($"A value for key {configKey} is missing in the App.config file.");
    
            return value;
        }
    }
    
    // Provider implementation that actually reads from the app.config file
    internal class AppConfigProvider
    {
        internal virtual string GetSetting(string configKey)
        {
            return ConfigurationManager.AppSettings[configKey];
        }
    }
    
    // In the test class the config values will be returned by a mock instead of a physical file. This example uses Moq as mocking framework.
    public class AppConfigTest
    {
        private Mock<AppConfigProvider> mock;
        private AppConfig appConfig;
    
        [SetUp]
        public void Setup()
        {
            mock = new Mock<AppConfigProvider>();
            appConfig = new AppConfig(mock.Object);
        }
    
        [Test]
        public void TestInputKeyWhenValueIsValid()
        {
            mock.Setup(provider => provider.GetSetting("InputKey")).Returns("12345");
    
            Assert.AreEqual("12345", appConfig.InputKey);
        }
    
    }
    
    //为获取某些配置设置而访问的类
    公共类AppConfig
    {
    //提供程序在lib发出时读取物理文件,但在测试中它将被模拟
    私有只读AppConfigProvider;
    //应用程序或库使用的构造函数
    公共AppConfig():此(新AppConfigProvider())
    {
    }
    //可由单元测试框架用于注入模拟的构造函数
    内部AppConfig(AppConfigProvider提供程序)
    {
    this.provider=提供者;
    }
    公共字符串InputKey=>GetConfigValueOrThrow(“InputKey”);
    私有字符串GetConfigValueOrThrow(字符串configKey)
    {
    字符串值=provider.GetSetting(configKey);
    如果(值==null)
    抛出新异常($“App.config文件中缺少键{configKey}的值。”);
    返回值;
    }
    }
    //实际读取app.config文件的提供程序实现
    内部类AppConfigProvider
    {
    内部虚拟字符串GetSetting(字符串配置键)
    {
    返回ConfigurationManager.AppSettings[configKey];
    }
    }
    //在测试类中,配置值将由模拟而不是物理文件返回。本例使用Moq作为模拟框架。
    公共类AppConfigTest
    {
    私人模拟;
    私有AppConfig-AppConfig;
    [设置]
    公共作废设置()
    {
    mock=新mock();
    appConfig=newappconfig(mock.Object);
    }
    [测试]
    public void TestInputKeyWhenValueIsValid()
    {
    mock.Setup(provider=>provider.GetSetting(“InputKey”))。返回(“12345”);
    AreEqual(“12345”,appConfig.InputKey);
    }
    }
    
    
    
    在.csproj文件中添加上述代码解决了我的问题

    由于我的要求是在.net framework和.net core中同时使用dll,所以我必须使用.net标准而不是.netcore或.netframework创建项目


    感谢@Panagiotis Kanavos的建议。

    这不是来自net standard 2+的“appsettings.json”吗?如果我使用appsettings.json,我可以将此类库用于.net framework项目吗?我已经在Nunit测试项目的.csproj中完成了上述工作。如果其他一些.net framework应用程序想要使用这个类库,他们是否也需要在那里添加上述代码?我的偏好是,他们只需引用dll并使用它。@Govind所有Microsoft.Extensions.*软件包都是.NET标准2.0,因此您可以在任何地方使用它们。您不需要使用
    appsettings.json
    无论如何,
    Configuration
    包可以与多个提供者一起工作。事实上,您可能应该使用config类和Secrets特性来保护输入密钥development@Govind如果您想在两个运行时都使用项目而不出现问题或警告,那么它必须是.NET标准的。这与配置无关。NET核心2.2。具有.NET Framework中不存在的API。当您从.NET Framework项目引用.NET核心程序集时,您的编译器应该已经在抱怨了,我可以这么做。但我的要求不是这样。我只想复制其他第三方消费者如何使用我的dll进行访问。因为我想在.net framework、.net core和其他平台上使用它,所以它应该与较低版本兼容。我的问题不是如何对app.config进行模拟。我倒是问了
    // The class that is accessed in order to get some config setting
    public class AppConfig
    {
        // The provider reads from a physical file when your lib is shipped but in your tests it will be mocked 
        private readonly AppConfigProvider provider;
    
        // Constructor used by your app or library
        public AppConfig() : this(new AppConfigProvider())
        {
        }
    
        // Constructor that can be used by your unit testing framework to inject a mock
        internal AppConfig(AppConfigProvider provider)
        {
            this.provider = provider;
        }
    
        public string InputKey => GetConfigValueOrThrow("InputKey");
    
        private string GetConfigValueOrThrow(string configKey)
        {
            string value = provider.GetSetting(configKey);
    
            if (value == null)
                throw new Exception($"A value for key {configKey} is missing in the App.config file.");
    
            return value;
        }
    }
    
    // Provider implementation that actually reads from the app.config file
    internal class AppConfigProvider
    {
        internal virtual string GetSetting(string configKey)
        {
            return ConfigurationManager.AppSettings[configKey];
        }
    }
    
    // In the test class the config values will be returned by a mock instead of a physical file. This example uses Moq as mocking framework.
    public class AppConfigTest
    {
        private Mock<AppConfigProvider> mock;
        private AppConfig appConfig;
    
        [SetUp]
        public void Setup()
        {
            mock = new Mock<AppConfigProvider>();
            appConfig = new AppConfig(mock.Object);
        }
    
        [Test]
        public void TestInputKeyWhenValueIsValid()
        {
            mock.Setup(provider => provider.GetSetting("InputKey")).Returns("12345");
    
            Assert.AreEqual("12345", appConfig.InputKey);
        }
    
    }
    
    <Target Name="CopyCustomContent" AfterTargets="AfterBuild"> 
    <Copy SourceFiles="app.config" DestinationFiles="$(OutDir)\testhost.dll.config" /> 
    </Target>