插件式的 WebApi 开发,首要面对的问题就是程序集的发现。因为开发的过程中,都是在各自的解决方案下进行开发,部署后是分模块放在一个整体的的运行时网站下。

约定

这里我根据上一节的设定,把插件打包完成后的文件夹,放入网站 bin 目录下。重复一下这样做的好处:在插件的配置或者程序集发生变动后,网站会直接重新启动。

这是 IIS 的机制,和 WebApi 无关。

  • 约定插件的文件夹名称使用 00_Name 的形式,可以更方便的按照我们的要求排列插件。
  • 约定插件的配置文件为插件根目录 PluginConfig.xml 文件
  • 约定插件的配置文件如下(后续随着功能的添加会适当添加内容)
<?xml version="1.0" encoding="UTF-8"?>
<configuration enabled="true">
<description>授权支持插件</description>
<assemblies>
<add type="relative">bin/Intime.AuthorizationService.dll</add>
<add type="relative">bin/Intime.AuthorizationService.Services.dll</add>
<add type="relative">bin/Intime.AuthorizationService.Data.dll</add>
<add type="relative">bin/Intime.AuthorizationService.Data.Repository.dll</add>
</assembiles>
</configuration>

解释一下 XML 配置文档的含义:

  • enabled="true" 表示当前插件的可用性,只有值为 true 的模块才会进行后续操作;否则不做任何操作。
  • description 子元素表示当前模块的自然语义名称,在程序上没有任何含义,面向自然人说明当前模块的作用。
  • assemblies 子元素表示当前模块下需要加载的程序集列表。
    • add 元素表示添加一个程序集文件:目前有且只有一个 add 元素受支持。
    • type 表示内含程序集路径的类型:
      • relative 表示相对路径,为程序集文件相对于当前配置文件的路径:比如第一个文件就是在当前目录的子目录 bin 目录下。
      • absolute 表示绝对路径,表示程序不必做额外工作就可以根据路径信息找到文件:此处没有栗子
    • 内含文本表示程序集的路径信息。

BuildManager 程序集加载规则

在实现程序集加载之前,我们有必要大概了解一下 BuildManager 类加载程序集的规则。

首先,是项目引用,被网站项目引用的 GAC 程序集,都会列入到引用列表中;其次,就是这个类很强大,只要你将程序集放入网站,它就能知道网站运行需要加载这个程序集;最后,还有个不常用的设置,Web.config 文件的 runtime 配置节点中引进的目录,也会被加载。所以我们要加载的程序集,必须是这三个地方所没有的程序集。

另外,就是程序集多版本的问题。这里我们约定更新的版本完全兼容老版本,否则就需要升级代码以适配这个功能。在网站运行出现多个版本存在的情况下,我们约定如下原则:

  • bin 目录是最先加载的路径,后续插件加载的程序集版本必须小于等于 bin 目录下程序集的版本。
  • 非 .Net 框架库自带的程序集,一律要拷贝到网站 bin 目录下:请使用 NuGet 管理第三方程序集。
  • 不要使用 Web.config 文件的 runtime 配置节点加载个性目录。

这样,我们可以定义包含这些元数据的类:配置文件信息、加载的程序集列表,在 PreApplicationStartMethodAttribute 程序集特性设定的方法内,将我们的程序集加到 BuildManager 管理的 程序集列表中。在程序运行时,.Net 就可以找到我们的这些程序集了。

部分源代码:自然语义

代码是在 Mac 下用文本编辑器写出来的,请自行脑补。

public class DynamicModule
{
public static DynamicModule Instance
{
get{ return Instance == null ? (Instance = new DynamicModule()) : Instance; }
} public string BaseDirectory { get; set; } public ModuleMetadata[] BaseDirectory { get; set; } ctor()
{
BaseDirectory = Path.Combine(App.BaseDirectory, "bin"); var modules = Directory.GetFiles(BaseDirectory, "PlugConfig.xml", AllDirectory)
.Where(p => p.Configuration.Enabled); bar baseAssemblies = AssemblyName.GetAssemblyNames(BaseDirectory, "*.dll", TopDirectory); var data = baseAssemblies.Intersect(modules.LoadedAssemblyNames)
.Where(p => p.CodeBase != BaseDirectory);
if(data.Any())
throw new ModuleConfiguration(string.Format("程序集 {0} 装载出现异常!", string.Join(data))); modules.Foreach(p => p.LoadAssemblies());
}
}

WebApi 插件式构建方案:发现并加载程序集的更多相关文章

  1. WebApi 插件式构建方案:集成加载数据库连接字符串

    body { border: 1px solid #ddd; outline: 1300px solid #fff; margin: 16px auto; } body .markdown-body ...

  2. WebApi 插件式构建方案:重写的控制器获取工厂

    body { border: 1px solid #ddd; outline: 1300px solid #fff; margin: 16px auto; } body .markdown-body ...

  3. WebApi 插件式构建方案:IOC 容器初始化

    body { border: 1px solid #ddd; outline: 1300px solid #fff; margin: 16px auto; } body .markdown-body ...

  4. WebApi 插件式构建方案

    WebApi 插件式构建方案 WebApi 插件式构建方案 公司要推行服务化,不可能都整合在一个解决方案内,因而想到了插件式的构建方案.最终定型选择基于 WebApi 构建服务化,之所以不使用 WCF ...

  5. Winfom 插件式(Plugins)/模块化开发框架-动态加载DLL窗体-Devexpress

    插件式(AddIn)架构,不是一个新名词,应用程序采用插件式拼合,可以更好的支持扩展.很多著名的软件都采用了插件式的架构,如常见的IDE:Eclipse,Visual Studio,SharpDeve ...

  6. MVC中未能加载程序集System.Web.Http/System.Web.Http.WebHost

    ==================================== 需要检查项目的Microsoft.AspNet.WebApi版本是否最新,System.Web.Http 这个命名空间需要更新 ...

  7. 分享JQuery动画插件Velocity.js的六种列表加载特效

    分享JQuery动画插件Velocity.js的六种列表加载特效.在这款实例中给中六种不同的列表加载效果.分别为从上飞入.从右侧飞入.从左侧飞入.和渐显.一起看下效果图: 在线预览   源码下载 实现 ...

  8. .Net Core 通过依赖注入和动态加载程序集实现宿程序和接口实现类库完全解构

    网上很多.Net Core依赖注入的例子代码,例如再宿主程序中要这样写: services.AddTransient<Interface1, Class1>(); 其中Interface1 ...

  9. C#在使用Assembly加载程序集时失败

    错误现象: 进行插件读取时出现错误:"尝试从一个网络位置加载程序集,在早期版本的 .NET Framework 中,这会导致对该程序集进行沙盒处理.此发行版的 .NET Framework ...

随机推荐

  1. Custom Exception in ASP.NET Web API 2 with Custom HttpResponse Message

    A benefit of using ASP.NET Web API is that it can be consumed by any client with the capability of m ...

  2. Python多级菜单

    作业2:多级菜单三级菜单可依次选择进入各子菜单所需新知识点:列表.字典 1.流程图 2.登录界面,输入对应索引 #!/usr/bin/env python3 # -*- coding:utf-8 -* ...

  3. 云计算与虚拟化KVM深度实践

    徐亮伟, 江湖人称标杆徐.多年互联网运维工作经验,曾负责过大规模集群架构自动化运维管理工作.擅长Web集群架构与自动化运维,曾负责国内某大型电商运维工作. 个人博客"徐亮伟架构师之路&quo ...

  4. could not be installed at this time

    无法下载应用 此时无法安装 Unable to Download App ''App" could not be installed at this time 编译程序的时候,Target ...

  5. vba截屏保存

    Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVa ...

  6. libcurl 调用curl_easy_getinfo( ) 返回错误码对照

    //执行设置好的操作 res = curl_easy_perform(easy_handle); //获取HTTP错误码 ; curl_easy_getinfo(easy_handle, CURLIN ...

  7. segment_object_model_3d

    * *********************************************************************** * This example program sho ...

  8. MonoBehaviour.OnValidate

    [MonoBehaviour.OnValidate] This function is called when the script is loaded or a value is changed i ...

  9. 虚拟机Mac系统中VMware_tools安装和vm共享文件夹的设置(转)

    原文来源: http://wenku.baidu.com/link?url=KRgfG40q2SEwZfde9xA7HVKjCsFBkMcf83tyellnzsHYZ_ErU1hWpVmTHYZem0 ...

  10. rsync同步常用命令[转载]

    转载:http://blog.csdn.net/niushuai666/article/details/16880061 如果你是一位运维工程师,你很可能会面对几十台.几百台甚至上千台服务器,除了批量 ...