Welcome

I’m a Chinese software engineer, here are all my experience.

在 Hugo 中集成 utterances 评论组件

utterances 是基于 GitHub issues 构建的轻量级评论小部件,通过此组件可以将 Github issues 应用于任何网站 前置条件 一个公开的 github repo 在该 repo 中安装utterances app 简单集成 打开utterances官网 在 configuration 节点填写 repo 信息等,填写好后会生成对应的组件代码 我使用的是 PaperMod 主题,将生成好的代码放入layouts/partials/comments.html <!--layouts/partials/comments.html--> <script src="https://utteranc.es/client.js" repo="[ENTER REPO HERE]" issue-term="pathname" theme="github-light" label="Comment" crossorigin="anonymous" async ></script> 然后在config.yaml中开启评论功能即可简单集成 params: comments: true 动态主题适配 PaperMod 主题有明亮和暗黑两种模式,而 comments 组件的主题是编码时就写在script标签中的,为了使 comments 组件的主题适配 PaperMod 主题,有以下两个步骤: 主题动态初始化 <!-- layouts/partials/comments.html --> <script> (function () { const theme = localStorage.getItem("pref-theme") === "dark" ? "github-dark" : "github-light"; const comment = document....

2023年1月24日

Newtonsoft.Json 小技巧

Newtonsoft.Json 是一个非常受欢迎的 .NET JSON 框架 一般来说大部分用户用到的方法主要就是 JsonConvert.SerializeObject 和 JsonConvert.DeserializeObject 方法 前者用于将 .NET 对象 序列化为 JSON 字符串,后者则是将 JSON 字符串反序列化为 .NET 对象 下面我将讲述一些你可能用过或者没用过的一些小技巧 填充对象 我现在有一个 {"name":"fissssssh"} JSON 对象,当将它转为Dictionary<string,string>后,可以通过键名name获取属性值 然而这个 JSON 现在变成 {"Name":"fissssssh"}, 无法再通过键名 name 获取属性值 Dictionary 是支持替换键名比较器的,但是 JsonConvert.DeserializeObject 只会调用其无参构造函数 我们可以手动将 Dictionary 创建出来, 然后通过 JsonConvert.PopulateObject 方法将 JSON 字符串序列化并填充至指定对象,代码如下 var json = "{\"Name\":\"fissssssh\"}"; // 创建一个键名忽略大小写的字典对象 var dict = new Dictionary<string,string>(StringComparer.InvariantCultureIgnoreCase); JsonConvert.PopulateObject(json, dict); // 使用 name 获取 JSON 中的 Name 属性值 var name = dict["name"];

2023年1月17日

使用 Visual Studio 调试 dapr 应用程序

dapr 应用程序是一个多进程程序,对于 Visual Studio 来说可能比较困难 这里介绍两种方法来使用 Visual Studio 调试 dapr 应用程序 使用 VS 扩展 附加进程调试 使用 VS 扩展 参考 https://github.com/dapr/dotnet-sdk/issues/401#issuecomment-747563695 准备条件 安装 PowerShell 7 / Core 也可使用 dotnet tool install --global PowerShell 进行安装 安装 VS 扩展 Microsoft Child Process Debugging Power Tool 2022 调试准备 编辑launchSettings.json { "$schema": "https://json.schemastore.org/launchsettings.json", "profiles": { "WebApplication1": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, "launchUrl": "weatherforecast", "applicationUrl": "http://localhost:5217", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "Dapr-PWSH": { "commandName": "Executable", "executablePath": "pwsh", "commandLineArgs": "-Command \"dapr run -a myapp -p 5217 -- dotnet run --no-build\"", "workingDirectory": "....

2023年1月5日

ASP.NET Core 中使用 Dapr 发布订阅

定义 subpub 组件 我们使用 Dapr 初始化时安装的 redis 作为 pubsub 的实现 创建文件 ~/.dapr/components/pubsub.yaml (Windows 用户为 %USERPROFILE%\.dapr\components\pubsub.yaml ),内容如下 Dapr 初始化后 ~/.dapr/components 文件夹会自动创建,里面有一个 statestore.yaml 的组件定义。如果没有该文件夹也不用担心,手动创建即可 apiVersion: dapr.io/v1alpha1 kind: Component metadata: name: pubsub spec: type: pubsub.redis version: v1 metadata: - name: redisHost value: localhost:6379 - name: redisPassword value: "" 创建项目 创建 ASP.NET Core WebAPI 项目 $ dotnet new webapi --no-openapi --no-https 安装 Dapr SDK dotnet CLI $ dotnet add package Dapr.AspNetCore 程序包管理器控制台 Install-Package Dapr.AspNetCore 也可以在 Visual Studio 的 Nuget 包管理器中搜索安装...

2022年12月14日

安装 Dapr

前置条件 Dapr 可以脱离 Docker 运行,但不在本篇所讲范围内,本篇内容中的操作都是基于 Docker 安装完成并运行正常的情况下的操作 Docker Docker 安装官方文档描述十分清晰。 Windows 用户推荐安装带界面的 Docker Desktop(更符合 Windows 人的操作习惯吧),Linux 用户安装 Docker Engine 即可。 开始安装 Dapr 的安装分为两部分: 安装 Dapr CLI 安装 Dapr Runtime 有两种方式可以进行安装,在线安装方式会去 github 下载对应的资源,网络不好的同学可以使用离线安装的方式 在线安装 安装 Dapr CLI Dapr 官网有各个操作系统详细的安装方法,这里讲一下通用的二进制安装方法: 首先去 Dapr CLI 的发布页(目前最新是 1.9.1 版本)下载对应操作系统版本的压缩包,命名格式为dapr_<os_name>_<cpu_arch>.(tar.gz|zip),如果操作系统或者 CPU 架构没选对,则 Dapr CLI 无法正常运行 通常来说 Windows 用户下载dapr_windows_amd64.zip,Linux 用户下载dapr_linux_amd64.tar.gz 解压到任意文件夹,并将该文件夹路径加入PATH环境变量 Linux 用户可直接创建软连接到/usr/local/bin/dapr, Windows 用户推荐将文件解压至%USERPROFILE%\bin\文件夹,并将%USERPROFILE%\bin\添加到PATH环境变量中,后续有其他的可执行文件也可以放入该文件夹,不用再动环境变量 打开控制台或者终端输入dapr,如果有相关的内容输出则安装成功 安装 Dapr Runtime 安装 Dapr Runtime 也叫初始化 Dapr。 本地 Dapr 环境的初始化很简单, 只需要dapr init即可...

2022年12月14日

Run Clash With Docker Desktop

创建docker-compose.yml version: '3.9' services: clash: container_name: core image: dreamacro/clash volumes: - ./config.yaml:/root/.config/clash/config.yaml:ro ports: - "7890:7890" # proxy port(change port to your config.yaml) - "9090:9090" # api port(change port to your config.yaml) restart: always yacd: container_name: web_ui image: haishanh/yacd ports: - "80:80" # change port which you want depends_on: - clash restart: always 启动 把你的clash配置文件 config.yaml 和 docker-compose.yml 放入同一个文件夹 然后执行 docker compose up -d 启动 打开 http://localhost:<your_yacd_exposed_port> 进入web UI 可以管理切换clash的节点和代理模式 设置系统代理 在 系统设置 -> 网络和Internet -> 代理 -> 手动设置代理 中填写clash暴露的http端口...

2022年7月9日

Visual Studio 2022 插件推荐

引言 插件可以提高开发人员的生产力,好的插件可以让开发事半功倍,下面推荐一些自己用的 Visual Studio 插件(免费!) 插件列表 以下所有插件在 Visual Studio 2022 运行正常,若版本不兼容请移步 Visual Studio Marketplace 查看是否有对应版本 插件名称 描述 CodeMaid VS2022 代码清理插件,其中有一个码锹窗口深得我心 Output enhancer 输出窗口使用彩色优化,错误为红色,警告为黄色等 Code alignment 代码对齐,让你的某些代码按照某个字符垂直对齐 Double-Click Maximize 2022 双击最大化,不用先拖出来再放大,再次双击即可回归原位 Time Stamp Margin 2022 在调试窗口左边增加一列时间戳 Shrink Empty Lines 2022 压缩空行和没有字符的行(只有括号的行)的高度,从而在屏幕上显示更多代码 Solution Error Visualizer 2022 当某个文件有错误或者警告时,在解决方案资源管理器中显示(其父目录也会显示) Match Margin 2022 在滚动条上显示当前选中单词的位置

2022年7月7日

如何在 ASP.NET Core WEB API 中启动后台任务

引言 有时候我们可能想在接口中开启一个后台任务,就像这样: public class MyController : Controller { private readonly MyDependency _dep; public MyController(MyDependency d) { _dep = d; } public IActionResult MyAction() { Task.Run(() => _dep.DoHeavyAsyncWork()); return Json("Your job is started!"); } } 事实上,这段代码很符合语义,接口也能成功返回。 但是其中有一个潜在问题,随着return语句响应本次请求,ASP.NET Core会开始释放本次请求的依赖,比如控制器和控制器依赖的各种服务……,这就会导致Task.Run语句中的所依赖的定义在控制器中的服务会被释放掉,这可能会导致一些未知的问题。这些潜在问题可能会让你的应用程序随时爆炸! 让后台任务拥有自己的生存期 为了保证后台服务的依赖不随控制器释放而释放,我们需要定义一个新的服务并将其注册为单例服务,因为单例服务永远不会被释放。 创建一个名为CannonService的类 CannonService.cs public class CannonService { private readonly ILogger<CannonService> _logger; private readonly IServiceProvider _serviceProvider; public CannonService(ILogger<CannonService> logger, IServiceProvider serviceProvider) { _logger = logger; _serviceProvider = serviceProvider; } public void Fire(Delegate dg, Action<Exception>?...

2022年6月27日

Create Redis Cluster by Docker Compose

Create a docker-compose.yml version: "3.9" services: redis-1: image: redis:7.0.2-alpine container_name: redis-1 ports: - "6371:6371" - "16371:16371" volumes: - ./node-1/data:/data - ./node-1/conf/redis.conf:/etc/redis/redis.conf networks: redis: ipv4_address: 172.28.0.11 command: - "redis-server" - "/etc/redis/redis.conf" redis-2: image: redis:7.0.2-alpine container_name: redis-2 ports: - "6372:6372" - "16372:16372" volumes: - ./node-2/data:/data - ./node-2/conf/redis.conf:/etc/redis/redis.conf networks: redis: ipv4_address: 172.28.0.12 command: - "redis-server" - "/etc/redis/redis.conf" redis-3: image: redis:7.0.2-alpine container_name: redis-3 ports: - "6373:6373" - "16373:16373" volumes: - ./node-3/data:/data - ./node-3/conf/redis.conf:/etc/redis/redis.conf networks: redis: ipv4_address: 172....

2022年6月21日

Css Integrity Error When Load Hugo Publish

问题描述 近日我使用 hugo 构建了我的博客,并通过 Github Action 将其发布在 Github Pages 上,刚开始还是很美好的,但是过一短时间以后打开页面发现样式全无,使用浏览器的开发者工具查看资源获取没有问题,但是在控制台却出现了这样一句话: Failed to find a valid digest in the 'integrity' attribute for resource '***' with computed SHA-256 integrity '***'. The resource has been blocked. 寻找原因 我在 MDN 上寻找到了关于 integrity 的定义,大概描述就是这是一个签名,浏览器获取到相应资源后会用相同的方法计算一个签名,只有签名相同时才会加载对应的资源,如果两个签名不一致则是文件完整性被破坏(文件发生了改变)。 问题来了,整个发布过程是由 Github Action 全自动操作的,没有人为干预,文件为何会无缘无故改变呢? 答案是 Cloudflare。 Cloudflare 中默认会开启静态资源的缓存来提高网站的加载速度,可是为什么缓存会改变文件呢?缓存并不会改变文件,在 Cloudflare 的 Speed > Optimization 中有一个叫 Auto Minify 的选项,描述如下: Reduce the file size of source code on your website. Note: Purge cache to have your change take effect immediately....

2022年6月20日