关于本站
想了解本站搭建所使用的组件,以及文章许可,请浏览 /en/posts/about 需要交流可在评论区留言,或者发送邮件至 ws_dev@163.com
想了解本站搭建所使用的组件,以及文章许可,请浏览 /en/posts/about 需要交流可在评论区留言,或者发送邮件至 ws_dev@163.com
The Arch Way Arch 的核心原则是 KISS(Keep It Simple Stupid)。这让它和 Ubuntu , RedHat 有着显著的区别。后者会考虑到开箱即用,而Arch不会,Arch会尽可能的保持和上游一致,而只做最小范围的更改。 Arch 崇尚的 KISS 不是站在使用者的角度出发的,而是站在维护者的角度出发的。软件打包或者说封装集成上,应该尽可能的的简单,最好什么都不做。然后提供手册,由用户自己要去进行组装配置。 本文将分享一个手动导入 archlinux-bootstrap 镜像文件,搭建基础的 ArchLinux WSL2 命令行环境的配置方法。 如果你觉得本文的配置方法太复杂,那么建议你使用 ArchWSL 项目,或者参考我编写的自动化配置脚本 。 当然对于 Arch 用户而言,折腾其实是一种乐趣。如果你体会不到这种乐趣,那么可能 Arch 并不适合你。 环境要求 win 10 / 11 最新版本系统 默认 WSL 版本为 2 wsl --set-default-version 2 已通过 wsl --install 安装过一个其他的 WSL2 发行版,或者有其他 Linux 机器。用于生成 rootfs 文件 我当前(2023/3/13)的软件版本为: wsl --version ---- WSL version: 1.1.3.0 Kernel version: 5.15.90.1 WSLg version: 1.0.49 MSRDC version: 1.2.3770 Direct3D version: 1.608.2-61064218 DXCore version: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp Windows version: 10.0.22621.1265 打包 rootfs ArchLinux 的镜像仓储中,会保存一份 archlinux-bootstrap-x86_64.tar.gz 文件,是当前最新版本的 bootstrap tar镜像。我们可以通过 tar/bsdtar 命令将其转换为 WSL 所需的 rootfs 文件。 ...
背景 autofac使用拦截器实现AOP,是基于Castle.Core的.然而Castle.Core并未提供原生异步支持.所以需要使用帮助类实现,这在autofac官方文档的已知问题中有详细说明。 对于该问题的讨论,最早出现于stackoverflow James Skimming基于其中的一个答案,研发了一个帮助包即: Castle.Core.AsyncInterceptor 我之前也一直使用的是该方案,不过thepirat000随后提出了一个使用dynamic的更加简化的实现方法 我对该方法进行了一些封装,实现了一个帮助包,大家可以尝试一下。 项目地址: https://github.com/wswind/lightwind 使用 使用时,你可以通过nuget安装Lightwind.Asyncinterceptor也可以直接拷贝AsyncInterceptorBase.cs放入你的项目中。样例代码可点击这里查看 其核心代码是封装实现一个支持异步处理的Interceptor父类,让开发者能够继承实现自己的拦截器。开发时,仅需关注所拦截的方法,在执行前后该添加什么处理逻辑. 异步拦截器的执行流程如下: 在所拦截的方法执行前,首先执行BeforeProceed,方法执行后,如果为同步方法,则后续执行AfterProceedSync 如果为异步方法,则await所拦截的方法使其真正执行后,调用AfterProceedAsync进行异步方法的后续处理。 对于异步执行且有返回值的情况,可通过hasAsynResult参数判断是否有返回值,通过ProceedAsynResult属性读取或修改所拦截方法的最终返回值. 代码的运行流程图如下: AsyncInterceptorBase.cs实现如下: // Licence: MIT // Author: Vincent Wang // Email: ws_dev@163.com // ProjectUrl: https://github.com/wswind/lightwind using System; using System.Reflection; using System.Runtime.CompilerServices; using System.Threading.Tasks; using Castle.DynamicProxy; namespace Lightwind.AsyncInterceptor { //inspired by : https://stackoverflow.com/a/39784559/7726468 public abstract class AsyncInterceptorBase : IInterceptor { public AsyncInterceptorBase() { } public void Intercept(IInvocation invocation) { BeforeProceed(invocation); invocation.Proceed(); if (IsAsyncMethod(invocation.MethodInvocationTarget)) { // 关键实现语句 invocation.ReturnValue = InterceptAsync((dynamic)invocation.ReturnValue, invocation); } else { AfterProceedSync(invocation); } } private bool CheckMethodReturnTypeIsTaskType(MethodInfo method) { var methodReturnType = method.ReturnType; if(methodReturnType.IsGenericType) { if (methodReturnType.GetGenericTypeDefinition() == typeof(Task<>) || methodReturnType.GetGenericTypeDefinition() == typeof(ValueTask<>)) return true; } else { if (methodReturnType == typeof(Task) || methodReturnType == typeof(ValueTask)) return true; } return false; } private bool IsAsyncMethod(MethodInfo method) { bool isDefAsync = Attribute.IsDefined(method, typeof(AsyncStateMachineAttribute), false); bool isTaskType = CheckMethodReturnTypeIsTaskType(method); bool isAsync = isDefAsync && isTaskType; return isAsync; } protected object ProceedAsyncResult { get; set; } private async Task InterceptAsync(Task task, IInvocation invocation) { await task.ConfigureAwait(false); await AfterProceedAsync(invocation, false); } private async Task<TResult> InterceptAsync<TResult>(Task<TResult> task, IInvocation invocation) { ProceedAsyncResult = await task.ConfigureAwait(false); await AfterProceedAsync(invocation, true); return (TResult)ProceedAsyncResult; } private async ValueTask InterceptAsync(ValueTask task, IInvocation invocation) { await task.ConfigureAwait(false); await AfterProceedAsync(invocation, false); } private async ValueTask<TResult> InterceptAsync<TResult>(ValueTask<TResult> task, IInvocation invocation) { ProceedAsyncResult = await task.ConfigureAwait(false); await AfterProceedAsync(invocation, true); return (TResult)ProceedAsyncResult; } protected virtual void BeforeProceed(IInvocation invocation) { } protected virtual void AfterProceedSync(IInvocation invocation) { } protected virtual Task AfterProceedAsync(IInvocation invocation, bool hasAsynResult) { return Task.CompletedTask; } } } 上述代码的关键实现语句为InterceptAsync((dynamic)invocation.ReturnValue, invocation),C#会在运行时依据invocation.ReturnValue的类型调用正确的重载函数,即:InterceptAsync / InterceptAsync<TResult> ...
AOP是所有现代OOP语言开发框架中的基础功能,在各类软件开发框架中有着广泛应用。虽然AOP早已不是什么新技术,可知其然还要其所以然。本文将基于.NET环境探讨实现AOP的底层原理。 本文为读书笔记 文中部分代码样例摘自Matthew D. Groves的《AOP in .NET》,推荐大家购买阅读。 中间件与过滤器原理截图摘自微软官方文档,请查看文中链接。 本文主要包含以下内容: 基础概念 ASP.NET Core框架内置的AOP 中间件 过滤器 AOP in .NET 编译时/运行时织入 代理模式 手动编写动态代理代码 Castle DynamicProxy Autofac + Castle.DynamicProxy 下载文中样例代码请访问 https://github.com/wswind/Learn-AOP 基础概念 面向对象编程通过类的继承机制来复用代码,这在大多数情况下这很有用。但是随着软件系统的越来复杂,出现了一些通过OOP处理起来相当费力的关注点,比如:日志记录,权限控制,缓存,数据库事务提交等等。它们的处理逻辑分散于各个模块,各个类方法之中,这违反了DRY原则(Don’t Repeat Yourself)以及关注度点分离原则(Separation of Concerns),不利于后期的代码维护。所谓AOP(面向切面编程),就是将这些关注点,看作一个个切面,捕获这些切面并将其处理程序模块化的过程。 以一个简单的日志记录切面处理为例。如果不应用AOP,日志处理的代码逻辑分散于模块的各个方法中,如下图 要实现AOP,关键在于捕捉切面,然后将切面织入(“weaving”)到业务模块中。 如下图代码中,我们将分散的日志处理代码模块化成了一个统一的切面处理程序:LogAspect。然后将其织入到BusinessModule1中,这就实现了日志处理的AOP。 ASP.NET Core框架内置的AOP机制 在.ASP.NET Core框架中,微软内置了一些处理AOP逻辑的机制。本质上它是Asp.NET Core框架通过管道-过滤器模式进行实现的。 虽然这与传统意义上语言层面的AOP不同,但是这里还是简单提一下。 中间件机制 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/ https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/write ASP.NET Core框架本身就是由一系列中间件组成的,它本身内置的异常处理,路由转发,权限控制,也就是在上述图中的请求管道中实现的。所以我们也完全可以基于中间件机制,实现AOP。 以异常处理为例,我可以将try catch加入到next方法的前后,以捕获后续运行过程中未处理的异常,并进行统一处理。代码如下: public class ExceptionHandlerMiddleware { private readonly RequestDelegate _next; public ExceptionHandlerMiddleware(RequestDelegate next ) { _next = next; } public async Task Invoke(HttpContext context, IHostingEnvironment env,ILogger<ExceptionHandlerMiddleware> logger) { try { await _next(context); } catch (Exception ex) { logger.LogError(new EventId(ex.HResult), ex, ex.Message); await context.HandleExceptionAsync(ex, env.IsDevelopment()); } } } 过滤器机制 https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters ...