这两天研究了下OrchardCMS系统,没搞明白如何加载模块的。
分析代码如下:
public class AssemblyAttributeModuleNamesProvider : IModuleNamesProvider { private readonly List<string> _moduleNames; public AssemblyAttributeModuleNamesProvider(IHostingEnvironment hostingEnvironment) { var assembly = Assembly.Load(new AssemblyName(hostingEnvironment.ApplicationName)); _moduleNames = assembly.GetCustomAttributes<ModuleNameAttribute>().Select(m => m.Name).ToList(); } public IEnumerable<string> GetModuleNames() { return _moduleNames; } }
这里,
assembly.GetCustomAttributes<ModuleNameAttribute>()
怎么就把多达69个模块加载了呢?
OrchardCore 中,如果某项目A依赖了某个模块B,会在A程序集中自动添加一个 ModuleNameAttribute,通常存在多个。
你用 .Net Reflector 查看 Web 项目,就会看到类似于下面的内容:
// Assembly XXX.Web, Version 1.0.0.0
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows=true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.EnableEditAndContinue |
......
[assembly: ModuleName("Tubumu.Modules.Admin")]
[assembly: ModuleName("Tubumu.Modules.Framework")]
[assembly: ModuleName("XXX.Modules.Core")]
......
而 assembly.GetCustomAttributes<ModuleNameAttribute>() 只是收集到这些 Attribute 而已。至于如何加载,可以参考下:https://blog.tubumu.com/2018/11/26/orchardcore-modular-and-multi-tenancy/
OrchardCore 中,如果某项目A依赖了某个模块B,会在A程序集中自动添加一个 ModuleNameAttribute,通常存在多个。
这个自定添加ModuleNameAttribute 是怎么做到的呢?一般我们编程都是自己手写上的.
模块之间的依赖关系是通过Nuget 包工具自动注入Assembly 属性来完成。在 OrchardCore.Cms.Web.csproj文件中引用了
<Import Project="..\OrchardCore\OrchardCore.Application.Targets\OrchardCore.Application.Targets.targets" />
在这个文件中,就定义了自动生成Assembly:ModuleNameAttribute 属性了。
<ItemGroup>
<AssemblyAttribute Include="OrchardCore.Modules.Manifest.ModuleNameAttribute" Condition="'@(ModuleNames)' != ''">
<_Parameter1>%(ModuleNames.Identity)</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
</Target>
OrchardCore 项目采用了Nuget工具包的方式,来实现自动注入的。要想了解Nuget工具包具体怎么操作,那就得去查Microsoft 官方文档了。也可以参考吕毅老师的文章:https://blog.walterlv.com/post/build-source-code-package-for-wpf-projects.html