关于如何将模块名添加到程序集的ModuleName说简单吧也简单,说不简单吧也不简单。

  简单的原因是代码只有几行,不简单的原因是这些都不是c#,都是MSbuild的代码。这可真难为我了,所以这个地方我卡了两个星期。

  首先我们来看下解决方案的目录:

  都知道这些文件夹都是解决方案文件夹,但是build解决方案文件夹里放的是什么,居然不是项目?不是项目如何调用呢,这可触及我的知识盲点。经过多方查阅资料和博问上提问,我重于搞清楚了。

  首先,这两个.yml文件删了也无所谓,我第一次见到yml文件还是在docker的配置上,也就是一个跟我们常用的json一样的配置文件(用缩进代替json里面那堆括号,有人觉得这样比较方便)。开始我还以为是通过其它程序靠yml配置文件注入模块,被误导了好久,这两个配置文件就是持续集成的配置文件(没进过大厂不懂这些被浪费好久),也就是项目发布到github会自动帮你build等等。

  其次,就是剩下的文件是靠Directory.Build.props和Directory.Build.targets调用到项目里的。这就是我的第二个知识盲点了。我们打开文件夹(直接打开资源管理器的,不是visual studio的),可以发现src源码文件夹下的OrchardCore、OrchardCore.Modules和OrchardCore.Themes三个文件夹都有Directory.Build.props和Directory.Build.targets这两个文件。这意味着还有文件不在项目里?这又怎么用呢?我真是快崩溃了!经过查找资料,重要明白:在MSBuild15以后新增一个功能就是让开发者可以自己定义项目信息放在一个文件,这个文件会在Microsoft.Common.props和Microsoft.Common.target引用,而且会在csproj项目文件所在的文件夹开始寻找,只要找到存在Directory.Build.props和Directory.Build.target文件就会自动导入里面的内容。也就是从项目的csproj当前项目开始自动向上寻找Directory.Build.props和Directory.Build.target,直到解决方法根目录,只要找到立即停止。这就是意味着每个项目编译的时候会把这些文件给包括进来。

  好了,明白了这些后,开始按顺序了解模块的加载过程。

  我是从启动项目OrchardCore.Cms.Web开始看,它项目引用了OrchardCore.Application.Cms.Core.Targets,而这个项目又引用了OrchardCore.Application.Targets,这下Targets项目都在OrchardCore文件夹下,也就是编译的时候会包含上面说的Directory.Build.props和Directory.Build.targets文件。

  OrchardCore.Application.Targets里面只有一个OrchardCore.Application.Targets.targets文件,打开如下:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <!--
This file is packaged with "OrchardCore.Application.Targets.nupkg" in "./build" such that any
Application that references it will embed in its assembly a list of the referenced modules.
--> <Target Name="ResolveModuleProjectReferences" AfterTargets="AfterResolveReferences">
<MSBuild
Targets="GetModuleProjectName"
BuildInParallel="$(BuildInParallel)"
Projects="@(_MSBuildProjectReferenceExistent)"
Condition="'@(_MSBuildProjectReferenceExistent)' != ''"
SkipNonexistentTargets="true"
ContinueOnError="true"> <Output ItemName="ModuleProjectNames" TaskParameter="TargetOutputs" />
</MSBuild> <ItemGroup>
<ModuleNames Include="@(ModulePackageNames);@(ModuleProjectNames)" />
</ItemGroup> <ItemGroup>
<AssemblyAttribute Include="OrchardCore.Modules.Manifest.ModuleNameAttribute" Condition="'@(ModuleNames)' != ''">
<_Parameter1>%(ModuleNames.Identity)</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
</Target> <Target Name="NoWarnOnRazorViewImportedTypeConflicts" BeforeTargets="RazorCoreCompile">
<PropertyGroup>
<NoWarn>$(NoWarn);0436</NoWarn>
</PropertyGroup>
</Target> </Project>

  看到AssemblyAttribute元素了吧,没错,这就是程序集的属性啊,在看看它里面有啥?OrchardCore.Modules.Manifest.ModuleNameAttribute,没错,这个就是上篇反射找到的ModuleName,那么怎么来的呢,有个Condition="'@(ModuleNames)' != ''",明显这个条件就是ModuleNames元素不为空,然后获取ModuleNames元素的Identity。那么我们顺着往上看就可以看到上个ItemGroup元素里面就包含ModuleNames,但是没有Identity属性啊,只能查阅资料了,谁叫我MSbuild两眼一抹黑呢,根据msdn介绍明白Identity就是Include属性中指定的项,大家也可以看看msdn。那么我们接着看INclude,@(ModulePackageNames);@(ModuleProjectNames),分号间隔符,间隔而已,继续看看第二个ModuleProjectNames,上面的MSBuid的Oupt就是了,而任务呢,就是MSBuild的GetModuleProjectName。这个任务在哪呢,感觉很无厘头是不是,不对,前面不是介绍了Directory.Build.props和Directory.Build.targets吗,没错,往里面找,打开Directory.Build.targets看看

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <Import Project="..\OrchardCore.Build\OrchardCore.Commons.targets" />
<Import Project="..\OrchardCore\OrchardCore.Module.Targets\OrchardCore.Module.Targets.targets" /> <PropertyGroup>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
</PropertyGroup> </Project>

  看到里面包含了的OrchardCore.Module.Targets.targets文件没有,打开接着看(这个有点长直接看最后部分):

 

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  ...

  <Target Name="GetModuleProjectName" Returns="@(ModuleProjectName)">
<ItemGroup>
<ModuleProjectName Include="$(AssemblyName)" />
</ItemGroup>
</Target> </Project>

  看到Name为GetModuleProjectName的Target任务了吧,请注意这个文件的位置,在..\OrchardCore\OrchardCore.Module.Targets\OrchardCore.Module.Targets.targets,没错就在OrchardCore.Module.Targets项目里,而所有模块都是以用这个项目,也就是说所有应用这个项目的项目名都会加到程序集的ModuleName上!

(四)学习了解OrchardCore笔记——将模块的名字添加到程序集的ModuleName的更多相关文章

  1. (五)学习了解OrchardCore笔记——灵魂中间件ModularTenantContainerMiddleware的第一行②模块的功能部分

    在(三)的时候已经说到模块集合用ForEachAsync的扩展方法分配多个任务,把每个modules的ManifestInfo分析出来的功能加入ConcurrentDictionary.我们先看看这个 ...

  2. (三)学习了解OrchardCore笔记——灵魂中间件ModularTenantContainerMiddleware的第一行①的模块部分

    了解到了OrchardCore主要由两个中间件(ModularTenantContainerMiddleware和ModularTenantRouterMiddleware)构成,下面开始了解Modu ...

  3. (二)学习了解OrchardCore笔记——开篇:OrchardCore的中间件

    现在开始看Starpup的中间件.这是一个扩展方法app.UseOrchardCore() public void Configure(IApplicationBuilder app, IHostEn ...

  4. (一)学习了解OrchardCore笔记——开篇:基于asp.net core的OrchardCore

    想深入了解OrchadCore源码许久了,但是读源码的时候遇到很多问题而网上的参考资料太少了(几乎都是OrchadCms不带OrchardCore的),现在解决得差不多了,做下笔记方便自己查看,有错误 ...

  5. python学习笔记013——模块

    1 模块module 1.1 模块是什么 模块是包含一系列的变量,函数,类等程序组 模块通常是一个文件,以.py结尾 1.2 模块的作用 1. 让一些相关的函数,变量,类等有逻辑的组织在一起,使逻辑更 ...

  6. hadoop2.5.2学习及实践笔记(四)—— namenode启动过程源码概览

    对namenode启动时的相关操作及相关类有一个大体了解,后续深入研究时,再对本文进行补充 >实现类 HDFS启动脚本为$HADOOP_HOME/sbin/start-dfs.sh,查看star ...

  7. Python学习的个人笔记(基础语法)

    Python学习的个人笔记 题外话: 我是一个大二的计算机系的学生,这份python学习个人笔记是趁寒假这一周在慕课网,w3cschool,还有借鉴了一些博客,资料整理出来的,用于自己方便的时候查阅, ...

  8. Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究

    Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究 一丶反射 什么是反射: ​ 反射的概念是由Smith在1982年首次提出的 ...

  9. Elasticsearch7.X 入门学习第一课笔记----基本概念

    原文:Elasticsearch7.X 入门学习第一课笔记----基本概念 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https: ...

随机推荐

  1. delphi 控件查询

    //老古董,以前这些东西太多了,收藏的没过来,只好粘贴至此,当然不是本人整理的. delphi 控件查询:http://www.torry.net/ http://www.jrsoftware.org ...

  2. Vuex怎么用(1)

    1. vuex是什么 github站点: https://github.com/vuejs/vuex在线文档: https://vuex.vuejs.org/zh-cn/简单来说: 对应用中组件的状态 ...

  3. 10TB级日志的秒级搜索

  4. JavaWeb网上图书商城完整项目--day02-6.ajax校验功能之页面实现

    1 .现在我们要在regist.js中实现ajax的功能,使用用户名到后台查询是否注册,邮箱是否到后台注册,验证码是否正确的功能 我们来看regist.js的代码 //该函数在html文档加载完成之后 ...

  5. 蒲公英 · JELLY技术周刊 Vol.12 尤雨溪新作 Vite, 你会支持么?

    「蒲公英」期刊,每周更新,我们专注于挖掘「基础技术.工程化.跨端框架技术.图形编程.服务端开发.桌面开发.人工智能」等多个大方向的业界热点,并加以专业的解读:不仅如此,我们还精选凹凸技术文章,向大家呈 ...

  6. php计算两个时间段内的 工作日 工作小时

    <?php class WorkTime { // 定义工作日 [1, 2, 3, 4, 5, 6, 0] public $week_workingday = [1, 2, 3, 4, 5]; ...

  7. Laravel 中自定义 手机号和身份证号验证

    首先在 Providers\AppServiceProvider.php 文件中自定义 手机号和身份证号验证 // AppServiceProvider.php 文件 <?php namespa ...

  8. 【JAVA8新的时间与日期 API】- 传统时间格式化的线程安全问题

    Java8之前的日期和时间API,存在一些问题,最重要的就是线程安全的问题.这些问题都在Java8中的日期和时间API中得到了解决,而且Java8中的日期和时间API更加强大. 传统时间格式化的线程安 ...

  9. 计算机网络之tcp与udp的区别

    1.基于连接与无连接: 2.对系统资源的要求(TCP较多,UDP少):3.UDP程序结构较简单:4.流模式与数据报模式 :5.TCP保证数据正确性,可靠稳定,UDP可能丢包:6.TCP保证数据顺序,U ...

  10. Jmeter系列(35)- 使用 ServerAgent 监控服务器

    如果你想从头学习Jmeter,可以看看这个系列的文章哦 https://www.cnblogs.com/poloyy/category/1746599.html 前言 做性能测试,监控服务器资源指标是 ...