用 AppContext 解决类库的更新兼容问题

文章转自吕毅博客,原文地址:https://blog.walterlv.com/post/dotnet/2017/09/30/app-context.html

还记得微软在 Mitigation: Pointer-based Touch and Stylus Support 中告诉大家如何在 .NET Framework 4.7 中迁移 WPF 的触控到基于 Pointer 消息?记得关键的 <AppContextSwitchOverrides value="Switch.System.Windows.Input.Stylus.EnablePointerSupport=true"/> 这一句吗?

有没有好奇为何这一句话能用来控制微软基础类库中某一块功能的行为呢?阅读本文将了解微软为开发者提供的一套类库更新的兼容性解决方案——AppContext


这是微软自 .NET Framework 4.6 开始为开发者们提供的方案。

比如你打算为你的类库增加了一个功能——指定一个文件夹名称用于存放文件。你写出了这样的代码:

// 1.0 版本的类库
public static class StorageSomeInfo
{
    public static void SetDirectoryName(string directoryName)
    {
        _directory = directoryName ?? throw new ArgumentNullException(nameof(directoryName));
        // 其他逻辑。
    }
}

故事背景

你将类库发布到 NuGet 上,一切运行安好。

直到有一天,某人给 directoryName 传入了空字符串。结果你的文件全部都不再存到指定的文件夹下,而是存到了根目录……这跟你的预期不符啊!

然而,类库发布了这么久,这么多人都下载安装使用了,要是随随便便把代码改成这样,搞不好一大堆小伙伴将面临着崩溃……(谁知道他们有没有依赖于你的 BUG 编程呢?搞不好他们绞尽脑汁发现这样还可以存到根目录呢于是就开开心心地用了呢!)

// 2.0 版本的类库
public static class StorageSomeInfo
{
    public static void SetDirectoryName(string directoryName)
    {
        if (string.IsNullOrWhitespace(directoryName))
            throw new ArgumentException(nameof(directoryName));
        // 其他逻辑。
    }
}

[Obsolete] 是一个好方案,他能够指导开发者一步步迁移他们对 API 的使用。不过:

  1. 如果调用的代码太多了,迁移起来就是个痛苦的差事儿。
  2. 难得取了个好名字,要知道取名字可是编程中最难的事儿之一啊!
  3. 更多的开发者们其实根本没意识到你写出了这个坑,于是凭什么让他们升级 API?!

使用 AppContext

这时候祭出——AppContext

将你的 2.0 代码改成这样:

// 2.0 版本的类库
public static class StorageSomeInfo
{
    public static void SetDirectoryName(string directoryName)
    {
        if (AppContext.TryGetSwitch("Switch.StorageSomeInfo.UseLegacyDirectoryName", out var flag)
            && flag == true)
            // 跑以前的代码
        else
            // 跑新的代码
         
        // 其他逻辑。
    }
}

那么开发者们更新你的类库时,就有可以挽回的方案了:

  1. 如果开发者们没有遇到什么问题,那么恭喜你那位开发者很幸运没有踩到你的坑,你平滑迁移过去了!
  2. 如果开发者们遇到了根目录问题,那么你的更新日志中的指导说明将起作用。

你可以在更新日志中写下说明:

  1. 建议开发者们修改此方法的调用,避免写出错误的代码;
  2. 如果开发者们很难改动这样的代码,可以要求开发者在 app.config 文件中添加以下代码以使用“遗弃的”逻辑。
<configuration>  
   <runtime>  
      <AppContextSwitchOverrides value="Switch.StorageSomeInfo.UseLegacyDirectoryName=true" />   
   </runtime>  
</configuration>  

更多 AppContext 的信息

开发者们如果有多个开关需要开启或关闭,则使用分号分隔多个开关:

<AppContextSwitchOverrides value="switchName1=value1;switchName2=value2" /> 

开发者们如果不想写配置文件,也可以直接在程序中调用:

AppContext.SetSwitch(string, bool);

当然,甚至可以直接动用注册表:HKLM\SOFTWARE\Microsoft\.NETFramework\AppContext 作为 Key,字符串作为 Value。依然是分号分割的键值对作为注册表项的值来存。如果采用注册表方案,将影响这台计算机上运行的所有程序。

这三种方式的优先级是:

  1. 代码中直接调用的优先级最高;
  2. 在 app.config 中指定的优先级其次;
  3. 在注册表中指定的优先级最低。

一点坑

在从 .NET Framework 4.6 升级到 4.7 后,注册表的方式貌似失效了。参考:FIX: AppContext switch overrides are not applied to applications that run on the .NET Framework 4.7

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
unapp云打包是一种在线应用打包工具,它可以将Web应用转化成原生应用,并可以适配不同的操作系统和设备。然而,有时候在使用unapp云打包过程中,可能会遇到dis(Disassembly)不兼容的问题。 dis不兼容问题通常是由于应用的代码或依赖库在不同的操作系统或设备上运行时出现了不兼容的情况。这种情况会导致dis过程中出现错误,进而影响到应用的打包结果。 要解决dis不兼容问题,可以尝试以下几个方法: 1. 检查代码和依赖库的兼容性:首先,针对不同的操作系统和设备,检查代码和依赖库是否具有相应的兼容性。可以查阅官方文档、开发者社区或相应的技术支持资源,找到解决方案或更新的版本。 2. 更新打包工具:如果dis不兼容是由于打包工具自身的问题导致的,可以尝试更新打包工具到最新版本。通常,打包工具会不断进行更新和改进,以修复兼容性问题和提供更好的支持。 3. 调整应用代码或依赖库:在一些情况下,可能需要对应用代码进行一些调整,以解决dis不兼容问题。可以尝试更新依赖库版本、修改特定的代码段或函数调用,或者使用特定的兼容性插件。 4. 寻求技术支持:如果以上方法都不能解决dis不兼容问题,可以联系相关的技术支持团队或开发者社区,向他们寻求帮助和解决方案。他们可能有更深入的了解和经验,能够提供更具体的指导和解决方案。 总之,解决unapp云打包dis不兼容问题需要结合具体情况综合考虑,并采取相应的措施。在开发过程中,持续的测试和验证是非常重要的,以确保打包过程的顺利进行和最终的应用质量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值