最近在将原有代码迁移.NET Core, 代码的迁移基本很快,当然也遇到了不少坑,重构了不少,后续逐步总结分享给大家。今天总结分享一下ConfigurationManager遇到的一个问题。

先说一下场景:

迁移.NET Core后,已有的配置文件,我们希望做到兼容,比如说app.config和web.config,

这样配置文件尽可能地和.NET Framework是一套,尽可能低保持一致。比如:appSettings自定义configSection等等。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="CustomConfigs" type="ClassLibraryNetStandard.CustomConfigHandler, ClassLibraryNetStandard"/>
</configSections>
<CustomConfigs>
<CustomConfig name="service1" order="0" reflectconfig="ClassLibraryNetStandard.TestService, ClassLibraryNetStandard"/>
<CustomConfig name="service2" order="1" reflectconfig="ClassLibraryNetStandard.TestService2, ClassLibraryNetStandard"/>
</CustomConfigs>
<appSettings>
<add key="service" value="service1"/>
</appSettings>
</configuration>

 对于上面配置读取我们做了以下几个事情

 1. 添加Nuget:System.Configuration.ConfigurationManager

   2. 保证原有自定义Section配置相关的代码、读取配置的代码,迁移到.NET Core后编译通过

   3. 修改配置文件、单元测试

 一、添加Nuget:System.Configuration.ConfigurationManager

搜索System.Configuration.ConfigurationManager:找到Nuget包,并添加引用:

二、保证原有自定义Section配置相关的代码、读取配置的代码,迁移到.NET Core后编译通过

示例代码中,自定义配置类CustomConfig

using System;
using System.Collections.Generic;
using System.Text; namespace ClassLibraryNetStandard
{
public class CustomConfig
{
public string Name { get; set; } public string ReflectConfig { get; set; } public int Order { get; set; }
}
}

同时对应的Section配置节解析类:CustomConfigHandler,实现接口:System.Configuration.IConfigurationSectionHandler

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml; namespace ClassLibraryNetStandard
{
public class CustomConfigHandler : System.Configuration.IConfigurationSectionHandler
{
public object Create(object parent, object configContext, XmlNode section)
{
var configs = new List<CustomConfig>(); //获取配置文件中自定义节点值
foreach (XmlNode childNode in section.ChildNodes)
{
string name = null;
var config = new CustomConfig();
if (childNode.Attributes["name"] != null)
{
name = childNode.Attributes["name"].Value;
config.Name = name; if (childNode.Attributes["order"] != null)
{
config.Order = Convert.ToInt32(childNode.Attributes["order"].Value);
}
if (childNode.Attributes["reflectconfig"] != null)
{
config.ReflectConfig = childNode.Attributes["reflectconfig"].Value;
} configs.Add(config);
}
} return configs;
}
}
}

同时,我们编写了一个简单的配置管理类:CustomConfigManager,其中有配置读取方法,直接读取配置文件:

        public static List<CustomConfig> GetCustomConfigs()
{
var sectionConfig = System.Configuration.ConfigurationManager.GetSection("CustomConfigs");
if (sectionConfig != null)
{
return sectionConfig as List<CustomConfig>;
} return null;
}

  

  这里我们使用了.NET Standard 2.0 library project,代码编译通过:

1>------ 已启动全部重新生成: 项目: ClassLibraryNetStandard, 配置: Debug Any CPU ------
1>C:\Program Files\dotnet\sdk\3.0.100-preview3-010431\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.RuntimeIdentifierInference.targets(151,5): message NETSDK1057: 你正在使用 .NET Core 的预览版。请查看 https://aka.ms/dotnet-core-preview
1>ClassLibraryNetStandard -> C:\Users\***\source\repos\NETFrameworkTest\ClassLibraryNetStandard\bin\Debug\netstandard2.0\ClassLibraryNetStandard.dll
========== 全部重新生成: 成功 1 个,失败 0 个,跳过 0 个 ==========

 三、修改配置文件、单元测试

添加MSTest单元测试工程:

增加App.config配置文件:

在单元测试方法中测试配置的读取:

       [TestMethod]
public void ConfigTest()
{
var configs = ClassLibraryNetStandard.CustomConfigManager.GetCustomConfigs();
Assert.IsNotNull(configs);
}

  原本以为,肯定可以获取到配置,实际获取的configs是null。

换了个Console类的应用,同样的配置文件读取,一点没有问题:

对比看了一下这两个工程,发现除了实际编译生成的配置文件名称不同,其他都一样。

问题肯定出在了单元测试工程上。Google了一下:有以下发现:

MSTest is running as testhost.dll, which means that ConfigurationManager is reading settings from testhost.dll.config when executing under .NET core. 
It will look for testhost.dll.config where the testhost.dll is located as the accepted answer states.
What is not mentioned is that it will also look for testhost.dll.config in the location where you have your test dlls.

  一句话:MSTest以testhost.dll运行,去取的配置文件是testhost.dll.config

这太尴尬了,直接无语,不过有两个解决方案:

1. 直接在单元测试工程中将app.config文件改为:testhost.dll.config

2. 修改单元测试工程文件,配置编译后事件,动态copy生成testhost.dll.config

试过之后,果真可以了,问题解决,分享给大家。

周国庆

2019/9/12

.NetCore技术研究-ConfigurationManager在单元测试下的坑的更多相关文章

  1. .NetCore技术研究-一套代码同时支持.NET Framework和.NET Core

    在.NET Core的迁移过程中,我们将原有的.NET Framework代码迁移到.NET Core.如果线上只有一个小型的应用还好,迁移升级完成后,只需要维护.NET Core这个版本的代码. 但 ...

  2. .NetCore技术研究-.NET Core迁移前的准备工作

    前段时间迁移.NET Core做了大量的试水和评估,今天整理一下分享给大家.大致有以下几个部分: 1. .NET Core的由来 2. 为什么要迁移.NET Core 3. .NET Core3.X主 ...

  3. .NetCore技术研究-EntityFramework Core 3.0 Preview

    前段时间.Net Core 3.0 发布了,Entity Framework Core 3.0 也发布了Preview版.假期用了一上午大致研究了一遍,同时又体验了一把Visual Studio 20 ...

  4. .NET Core技术研究系列-索引篇

    随着.NET Core相关技术研究的深入,现在将这一系列的文章,整理到一个索引页中,方便大家翻阅查找,同时,后续也会不断补充进来. .NET Core技术研究-WebApi迁移ASP.NET Core ...

  5. 重复数据删除(De-duplication)技术研究(SourceForge上发布dedup util)

    dedup util是一款开源的轻量级文件打包工具,它基于块级的重复数据删除技术,可以有效缩减数据容量,节省用户存储空间.目前已经在Sourceforge上创建项目,并且源码正在不断更新中.该工具生成 ...

  6. 伪AP检测技术研究

    转载自:http://www.whitecell-club.org/?p=310 随着城市无线局域网热点在公共场所大规模的部署,无线局域网安全变得尤为突出和重要,其中伪AP钓鱼攻击是无线网络中严重的安 ...

  7. Azure IoT 技术研究系列2-起步示例之设备注册到Azure IoT Hub

    上篇博文中,我们主要介绍了Azure IoT Hub的基本概念.架构.特性: Azure IoT 技术研究系列1-入门篇 本文中,我们继续深入研究,做一个起步示例程序:模拟设备注册到Azure IoT ...

  8. selenium相关技术研究(从1.0-3.0)

    注: 以下内容引自http://www.cnblogs.com/hhudaqiang/p/6550135.html Selenium相关技术研究(从1.0-3.0) 好吧,最近看wxpython有点多 ...

  9. 【转】手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)

    1.引言 特别说明:本文内容仅用于即时通讯技术研究和学习之用,请勿用于非法用途.如本文内容有不妥之处,请联系JackJiang进行处理!   我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...

随机推荐

  1. restapi(4)- rest-mongo : MongoDB数据库前端的httpserver

    完成了一套标准的rest风格数据库CRUD操作httpserver后发现有许多不足.主要是为了追求“通用”两个字,想把所有服务接口做的更“范generic”些,结果反而限制了目标数据库的特点,最终产生 ...

  2. 基于 kubeadm 部署单控制平面的 k8s 集群

    单控制平面不符合 HA 要求,但用于开发/测试环境不会有任何问题,如果资源足够的话(10台以上服务器,3台用于APIserver.3台用于 etcd 存储.至少3台用于工作节点.1台作为负载均衡),可 ...

  3. 利用DoHome APP和音箱控制继电器通断电实验参考步骤

    准备材料: Arduino Uno 一块 Arduino 扩展板        购买链接 DT-06模块一个       购买链接 安卓手机一个 小度音箱一个 继电器模块一个 杜邦线若干 1.DT-0 ...

  4. ASP.NET Core on K8S深入学习(3-2)DaemonSet与Job

    本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章. 上一篇<3-1 Deployment>中介绍了Deployment ...

  5. java-初读 HashTable

    有用的标识符 transiant 有用的属性 初始容量11 加载因子0.75 这里理解如果要经常插入大量数据可以增大加载因子 有用的方法 @Test public void testNan() { l ...

  6. ASP.NET Core MVC 之区域(Area)

    区域(Area)是一个 ASP.NET MVC 功能,用于将相关功能组织为一个单独的命名空间(用于路由)和文件结构(用于视图).使用区域通过向控制器和操作添加 一个路由参数(area)来创建用于路由目 ...

  7. 通过Blazor使用C#开发SPA单页面应用程序(4) - Ant Design Button

    前面学习了Blazor的特点.环境搭建及基础知识,现在我们尝试的做个实际的组件. Ant Design是蚂蚁金服是基于Ant Design设计体系的 UI 组件库,主要用于研发企业级中后台产品.目前官 ...

  8. 自定义Dialog---实现优美对话框

    PS:自定义dialog,一些系统的dialog已经不能满足开发人员的需求了,所以,我们需要自定义一个属于并且适合自己项目的对话框,无论是颜色还是功能需求上都是和自己的项目紧密相关的,一些系统的对话框 ...

  9. python学习之路(1)---编程语言,变量

    编程语言的类型分为三大类:1.机器语言:01010的二进制语言,执行速度快,开发效率低2.汇编语言:把0101转换成我们可以看懂的字母,执行速度快,开发效率低3.高级语言 : 编译型语言:把源代码编程 ...

  10. CRNN+CTC (基于CTPN 的end-to-end OCR)

    1. https://zhuanlan.zhihu.com/p/43534801  (详细原理) 2. https://blog.csdn.net/forest_world/article/detai ...