取消

都是用 DllImport?有没有考虑过自己写一个 extern 方法?

你做 .NET 开发的时候,一定用过 DllImport 这个特性吧,这货是用于 P/Invoke (Platform Invoke, 平台调用) 的。这种 DllImport 标记的方法都带有一个 extern 关键字。 那么有没有可能我们自己写一个自己的 extern 方法呢?答案是可以的。本文就写一个这样的例子。 DllImport 日常我们的平台调用代码是这样的: c...

深入了解 WPF Dispatcher 的工作原理(PushFrame 部分)

在上一篇文章 深入了解 WPF Dispatcher 的工作原理(Invoke/InvokeAsync 部分) 中我们发现 Dispatcher.Invoke 方法内部是靠 Dispatcher.PushFrame 来确保“不阻塞地等待”的。然而它是怎么做到“不阻塞地等待”的呢? 阅读本文将更深入地了解 Dispatcher 的工作机制。 本文是深入了解 WPF Dispatcher...

用 dotTrace 进行性能分析时,Timeline 打不开?无法启动进程?也许你需要先开启系统性能计数器的访问权限

对 .NET 程序使用 dotTrace 进行性能分析时,你也可能遭遇到 dotTrace 的 Bug。我就遇到了性能分析选项 Timeline 打不开进程的情况。 dotTrace 的性能分析选项 dotTrace 启动性能分析的选项有四个,你可以阅读 用 dotTrace 进行性能分析时,各种不同性能分析选项的含义和用途 了解不同选项的含义和用途,以便对你的性能分析提供更多的...

了解 .NET/C# 程序集的加载时机,以便优化程序启动性能

林德熙在 C# 程序集数量对软件启动性能的影响 一文中说到程序集数量对程序启动性能的影响。在那篇文章中,我们得出结论,想同类数量的情况下,程序集的数量越多,程序启动越慢。 额外的,不同的代码编写方式对程序集的加载性能也有影响。本文将介绍 .NET 中程序集的加载时机,了解这个时机能够对启动期间程序集的加载性能带来帮助。 程序集加载方式对性能的影响 为了直观地说明程序集加载方式对...

出让执行权:Task.Yield, Dispatcher.Yield

Yield 这个词很有意思,叫做“屈服”“放弃”“让步”,字面意义上是让出当前任务的执行权,转而让其他任务可以插入执行。Task、Dispatcher、Thread 都有 Yield() 方法,看起来都可以让出当前任务的执行权。 如果在阅读中发现对本文涉及到的一些概念不太明白,可以阅读: 深入了解 WPF Dispatcher 的工作原理(Invoke/InvokeAsyn...

课程 预编译框架,开发高性能应用 - 微软技术暨生态大会 2018

微软技术暨生态大会(Tech Summit),2018 年在上海世博中心召开。这是最后一次的 Tech Summit 了;明年开始,中国大陆地区就要和其他国家和地区一样,进行全球 Ignite Tour 了。 我也有幸成为分会场讲师团队的一员,课程是《预编译框架 - 开发高性能应用》。内容就是我博客中与 MSBuild / Roslyn / dotnet / NuGet 相关的内容;我们将...

WPF 中的 NameScope

我们在 WPF 中使用绑定时可以使用 ElementName=Foo 这样的写法,并且还能够真的在运行时找到这个名称对应的对象,是因为 WPF 中提供了名称范围概念。 实现 INameScope 接口可以定义一个名称范围。无论你使用 Name 属性还是使用 x:Name 特性都可以在一个名称范围内指定某个元素的名称。绑定时就在此名称范围内查找,于是可以找到你需要的对象。 本文将介绍 WP...

将 UWP 中 CommandBar 的展开方向改为向下展开

在 UWP 中使用 CommandBar 来迅速添加一组功能按钮是非常迅速的,是 UWP 中推荐的交互方案之一。也许你能见到 CommandBar 按你所需向下展开,不过可能更多数情况会看到 CommandBar 的展开方向是向上的。 本文将解释 CommandBar 的展开方向逻辑,并且提供多种方法来解决它展开方向的问题。 为什么我们需要更改 CommandBar 的展开方向?...

各个 C# 版本的主要特性、发布日期和发布方式(C# 1.0 - 7.3)

本文收集各个 C# 版本的主要特性、发布日期和发布方式。 C# 8.0 尚在预览版本 C# 7.3 2018 年 5 月 随 Visual Studio 2017 v15.7 发布 C# 7.2 2017 年 11 月 随 Visual Studio 2017 v15.5 发布 C# 7.1 2017 年 8 月 随 Visual...

WPF 的 ElementName 在 ContextMenu 中无法绑定成功?试试使用 x:Reference!

在 Binding 中使用 ElementName 司空见惯,没见它出过什么事儿。不过当你预见 ContextMenu,或者类似 Grid.Row / Grid.Column 这样的属性中设置的时候,ElementName 就不那么管用了。 本文将解决这个问题。 以下代码是可以正常工作的 <Window x:Class="Walterlv.Demo.BindingCont...

分析现有 WPF / Windows Forms 程序能否顺利迁移到 .NET Core 3.0(使用 .NET Core 3.0 Desktop API Analyzer )

今年五月的 Build 大会上,微软说 .NET Core 3.0 将带来 WPF / Windows Forms 这些桌面应用的支持。当然,是通过 Windows 兼容包(Windows Compatibility Pack)实现的。为了提前检查你的程序是否能在未来跑在 .NET Core 3.0 上,微软在 2018年8月8日 推出了 .NET Core 3.0 Desktop API ...

使用并解析 OPML 格式的订阅列表来转移自己的 RSS 订阅(解析篇)

OPML 全称是 Outline Processor Markup Language ,即 大纲处理标记语言。目前流行于收集博客的 RSS 源,便于用户转移自己的订阅项目。 本文将介绍这个古老的格式,并提供一个 .NET 上的简易解析器。 本文是两个部分的第二篇,前者是理解 OPML 格式,此篇是解析此格式: 概念篇 解析篇(本文) OPML 格式 在解析之前,...

Git 更安全的强制推送,--force-with-lease

由于 git rebase 命令的存在,强制将提交推送到远端仓库似乎也有些必要。不过都知道 git push --force 是不安全的,这让 git rebase 命令显得有些鸡肋。 本文将推荐 --force-with-lease 参数,让我们可以更安全地进行强制推送。 --force-with-lease 参数自 Git 的 1.8.5 版本开始提供,只在解决 git push...

再也不用克隆多个仓库啦!git worktree 一个 git 仓库可以连接多个工作目录

我在 feature 分支开发得多些,但总时不时被高优先级的 BUG 打断需要临时去 develop 分一个分支出来解 BUG。git 2.6 以上开始提供了 worktree 功能,可以解决这样的问题。 阅读本文将了解使用 git worktree 高效进行并行开发的方法。 git worktree 从一个仓库中可以创建多个工作目录,方便多开编辑器并行开发。 快速上手 git ...

.NET 命令行参数包含应用程序路径吗?

如果你关注过命令行参数,也许发现有时你会在命令行参数的第一个参数中中看到应用程序的路径,有时又不会。那么什么情况下有路径呢? 其实是否有路径只是取决于获取命令行参数的时候用的是什么方法。而这是 Windows 操作系统的机制,与具体的运行环境无关。 测试程序 考虑下面这样的测试程序: using System; using System.Globalization; nam...

WPF 同一窗口内的多线程 UI(VisualTarget)

WPF 的 UI 逻辑只在同一个线程中,这是学习 WPF 开发中大家几乎都会学习到的经验。如果希望做不同线程的 UI,大家也会想到使用另一个窗口来实现,让每个窗口拥有自己的 UI 线程。然而,就不能让同一个窗口内部使用多个 UI 线程吗? 阅读本文将收获一份对 VisualTarget 的解读以及一份我封装好的跨线程 UI 控件 DispatcherContainer.cs。 WPF...

.NET/C# 推荐一个我设计的缓存类型(适合缓存反射等耗性能的操作,附用法)

这里我想说的是类型“实例”的缓存,适用于那些实例或者值计算很耗时的操作。典型的场景如反射获取 Attribute。 适用 本文推荐的方法适用于相同的输入可以获得相同的输出,但是这个输入到输出的过程非常耗时。 大家都知道反射是很耗时的,尤其是获取 Attribute 和反射调用实例的方法。而从一个反射的成员中得到其 Attribute 是唯一的输入对应唯一的输出。 思路 既然...

.NET/C# 使用反射调用含 ref 或 out 参数的方法

使用反射,我们可以很容易地在运行时调用一些编译时无法确定的属性、方法等。然而,如果方法的参数中包含 ref 或 out 关键字的时候,又该怎么调用呢? 本文将介绍如何反射调用含 ref 或 out 关键字的方法。 比如我们有这样的类型: public class Walterlv { public string Get(string key) { } } ...

.NET/C# 使用反射注册事件

使用反射,我们可以很容易地在运行时调用一些编译时无法确定的属性、方法等。那么如何注册事件呢? 本文将介绍如何使用反射注册事件。 不使用反射 例如,我们希望反射的类型是这样的: public class Walterlv { public event EventHandler BlogPublished; } 那么只需要使用如下代码即可完成事件的注册: var w...

.NET/C# 判断某个类是否是泛型类型或泛型接口的子类型

.NET 中提供了很多判断某个类型或实例是某个类的子类或某个接口的实现类的方法,然而这事情一旦牵扯到泛型就没那么省心了。 本文将提供判断泛型接口实现或泛型类型子类的方法。 .NET 中没有自带的方法 对于实例,.NET 中提供了这些方法来判断: if (instance is Foo || instance is IFoo) { } 对于类型,.NET 中提供了这些方法来...

Win32 程序在启动时激活前一个启动程序的窗口

UWP 程序天生单实例。当然,新 API (10.0.17134)开始也提供了多实例功能。不过,传统 Win32 程序可就要自己来控制单实例了。 本文介绍简单的几个 Win32 方法调用,使 Win32 程序也支持单实例。 激活之前进程的窗口 我们可以通过进程名称找到此前已经启动过的进程实例,如果发现,就激活它的窗口。 [STAThread] static void Main...

Windows 无法删除文件夹 —— 访问被拒绝 / 因为目录不是空的

在日常使用 Windows 10 时,有时会遇到删除很普通的文件夹时提示“访问被拒绝”,以管理员权限重试后依然提示没有权限。如果使用命令行删除,则会提示“无法删除文件夹 XXX,目录不是空的。”。 本文将介绍其原因并提供解决方案。 删除文件夹遭到拒绝 有时我们在删除一个很普通的文件夹时,会提示需要提升权限才能删除。 ▲ 需要提升权限 其实按照经验,这种问题与权限并没有什么...

在操作系统重启后恢复应用程序的工作状态

Windows 10 创意者更新之后,默认开启了重启后恢复应用程序状态的功能。这是自 Vista 以来就提供的功能——Restart Manager。 应用程序实现这一功能只需要调用 RegisterApplicationRestart 即可。传入两个参数: 重启后使用的命令行参数(例如当前正在打开的文件,以及正在阅读或编辑的位置) 决定是否进行重启的限制标记(任何时候都能...

为带有多种语言的 Jekyll 博客添加多语言选择

我有几篇博客是用多种语言编写的,一开始我是在每篇博客中添加其他语言的链接,但多语言博客多了之后就成了复制粘贴了。是时候做一个通用的布局来实现多语言博客了! 本文将为大家提供一个我编写好的多语言博客选择器(MIT License)。 先来看看效果。现在,请选择一个阅读语言: English ...

屏幕上那个灰色带有数字的框是什么?看着好难受!

为什么屏幕上出现了一个灰框,里面有黑色数字,而且还不消失?强迫症难以忍受啊! ▲ 就是这个置于所有窗口最顶层,怎么也去不掉的灰色数字框 强迫症晚期请直接前往最后一节把它消灭好了,非强迫症晚期的我们一起来探究下它到底是什么。 使用 Spy++ 想探究一个界面属于哪个进程,当然少不了 Spy++。现在,我们去 Visual Studio 中找到并打开 Spy++。 于是,...

(C#)if (this == null)?你在逗我,this 怎么可能为 null!用 IL 编译和反编译看穿一切

if (this == null) Console.WriteLine("this is null"); 这句话一写,大家一定觉得荒谬,然而 if 内代码的执行却是可能的!本文讲介绍到底发生了什么。 制造一个 this 可以为 null 的程序 请看代码,这是我们的库函数: namespace Walterlv.Demo { public class Foo {...

使用 GitVersion 在编译或持续构建时自动使用语义版本号(Semantic Versioning)

我们在之前谈过 语义版本号(Semantic Versioning),在项目中应用语义版本号能够帮助库的开发者在发布包时表明更多的语义信息。这是趋势,从微软的博客 Versioning NuGet packages in a continuous delivery world 三部曲中可以看出,从 NuGet 4.3.0 以及 Visual Studio 2017 15.3 以上版本开始支持...

Automatically increase the semantic version using GitVersion

I wrote another post talking about Semantic Versioning before (but it is not in English). Introducing the semantic version to a project can give library users more semantic information when library...

使用 Emit 生成 IL 代码

.NET Core/.NET Framework 的 System.Reflection.Emit 命名空间为我们提供了动态生成 IL 代码的能力。利用这项能力,我们能够在运行时生成一段代码/一个方法/一个类/一个程序集。 本文将介绍使用 Emit 生成 IL 代码的方法,以及在此过程中可能遇到的各种问题。 在编写以下代码时如果遇到一些意料之外的错误,希望调试生成的 IL 代码,可以...

让你编写的控件库在 XAML 中有一个统一的漂亮的命名空间(xmlns)和命名空间前缀

在 WPF XAML 中使用自己定义的控件时,想必大家都能在 XAML 中编写出这个控件的命名空间了。然而——我写不出来,除非借助 ReSharper。 如果控件能够有一个漂亮的命名空间和命名空间前缀呢?——好吧,还是写不出来,不过,至少漂亮些。本文将指导你自定义在 XAML 中使用的命名空间。 达到什么样的效果? <UserControl x:Class="Hu...