最近在将原有代码迁移.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. Java模拟并解决缓存穿透

    什么叫做缓存穿透 缓存穿透只会发生在高并发的时候,就是当有10000个并发进行查询数据的时候,我们一般都会先去redis里面查询进行数据,但是如果redis里面没有这个数据的时候,那么这10000个并 ...

  2. Golang高效实践之array、slice、map

    前言 Golang的slice类型为连续同类型数据提供了一个方便并且高效的实现方式.slice的实现是基于array,slice和map一样是类似于指针语义,传递slice和map并不涉及底层数据结构 ...

  3. kafka消息的处理机制(五)

    这一篇我们不在是探讨kafka的使用,前面几篇基本讲解了工作中的使用方式,基本api的使用还需要更深入的去钻研,多使用才会有提高.今天主要是探讨一下kafka的消息复制以及消息处理机制. 1. bro ...

  4. C++这么难,为什么还要学习C++呢?如何学?

    在大多数开发或者准开发人员的认识中,C/C++ 是一门非常难的编程语言,很多人知道它的强大,但因为认为“难”造成的恐惧让很多人放弃. 这个世界本来就是残酷的,所以你不能怪C++向你展示了世界的本质 大 ...

  5. Linux系统关机与重新引导流程简介

    引言 在<Linux启动之旅>中,我们了解了Linux的启动过程,下面我们一同来学习Linux关机与重新引导流程. 不同于桌面系统,作为服务器,我们较少对Linux系统进行系统重启,但在以 ...

  6. 【模板】zkw线段树

    题意简述 已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 代码 #include <cstdio> using namespace std; in ...

  7. 【Python3爬虫】爬取美女图新姿势--Redis分布式爬虫初体验

    一.写在前面 之前写的爬虫都是单机爬虫,还没有尝试过分布式爬虫,这次就是一个分布式爬虫的初体验.所谓分布式爬虫,就是要用多台电脑同时爬取数据,相比于单机爬虫,分布式爬虫的爬取速度更快,也能更好地应对I ...

  8. ubuntu-18.10 虚拟机 配置网络环境

    查询主机系统ip 使用virtualbox 设置网络模式为桥接模式 设置静态 ip 与网关 关闭防火墙 sudo ufw disable

  9. ansible模块介绍之ios_facts

    一.模块简介 收集运行IOS系统的(此处指思科的ios)的远端设备信息 二.模块参数 auth_pass #特权密码,如果参数authorize=no,则不会检索此密码,如果任务task不指定,则默认 ...

  10. BeanUtils开发包的使用

    对内省技术有了一定的了解之后,我们就可以来学习一下BeanUtils开发包的使用了. 我们先假设一个情景,有一个JSP文件,如果要将该JSP文件中表单数据封装到Servlet文件应该怎么办?此时方法显 ...