C#动态加载程序集的全攻略

 更新时间:2025年08月08日 09:11:46   作者:墨瑾轩  
在 C# 中,动态加载程序集是一种常见的需求,特别是在需要模块化、插件化或运行时扩展功能的场景中,以下是如何实现 C# 代码依赖的动态加载的详细说明,结合了知识库中的关键信息和实际应用技巧,需要的朋友可以参考下

引言

在 C# 中,动态加载程序集(Dynamic Assembly Loading)是一种常见的需求,特别是在需要模块化、插件化或运行时扩展功能的场景中。以下是如何实现 C# 代码依赖的动态加载的详细说明,结合了知识库中的关键信息和实际应用技巧。

一、动态加载程序集的核心方法

C# 提供了多种方式动态加载程序集,以下是三种常用方法及其区别:

1. Assembly.Load

  • 特点
    • 通过程序集名称加载(不带路径)。
    • 会自动加载依赖项(如果依赖项在 GAC 或当前目录中)。
    • 适合已知程序集名称且依赖项已存在的场景。
  • 示例
Assembly assembly = Assembly.Load("MyAssembly");

2. Assembly.LoadFrom

  • 特点
    • 通过文件路径加载程序集(支持相对或绝对路径)。
    • 会自动加载依赖项(如果依赖项在 GAC 或当前目录中)。
    • 即使路径不同,相同名称的程序集 会被视为同一实例。
  • 示例
Assembly assembly = Assembly.LoadFrom("C:\\MyAssembly.dll");

3. Assembly.LoadFile

  • 特点
    • 通过文件路径加载程序集,不自动加载依赖项
    • 可以加载多个同名但不同路径的程序集(视为不同实例)。
    • 需要手动处理依赖项加载(通过 AppDomain.AssemblyResolve 事件)。
  • 示例
Assembly assembly = Assembly.LoadFile("C:\\MyAssembly.dll");

二、动态加载程序集的完整流程

以下是一个完整的动态加载程序集并调用其功能的示例:

1. 加载程序集

string path = @"C:\MyAssembly.dll";
Assembly assembly = Assembly.LoadFile(path);

2. 获取类型并创建实例

// 获取类型(需指定命名空间和类名)
Type type = assembly.GetType("MyNamespace.MyClass");

// 创建实例(无参构造函数)
object instance = Activator.CreateInstance(type);

3. 调用方法

// 获取方法信息
MethodInfo method = type.GetMethod("MyMethod");

// 调用方法(无参)
method.Invoke(instance, null);

4. 处理依赖项(如果使用 LoadFile)

如果程序集依赖其他 DLL,需通过 AppDomain.AssemblyResolve 事件手动加载依赖项:

AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
    string dependencyPath = @"C:\MyDependency.dll";
    return File.Exists(dependencyPath) ? Assembly.LoadFile(dependencyPath) : null;
};

三、动态加载的典型应用场景

1. 插件系统

通过动态加载外部 DLL 实现模块化扩展:

// 加载插件
Assembly pluginAssembly = Assembly.LoadFrom("Plugin.dll");

// 查找所有实现 IPlugin 接口的类型
foreach (Type type in pluginAssembly.GetTypes())
{
    if (typeof(IPlugin).IsAssignableFrom(type) && !type.IsInterface)
    {
        IPlugin plugin = (IPlugin)Activator.CreateInstance(type);
        plugin.Execute();
    }
}

2. 模块化应用

根据用户配置动态加载功能模块:

string moduleName = "ModuleA";
Assembly moduleAssembly = Assembly.Load(moduleName);
Type moduleType = moduleAssembly.GetType($"{moduleName}.ModuleClass");
object moduleInstance = Activator.CreateInstance(moduleType);

3. 动态资源加载

动态加载资源文件(如语言包):

Assembly resourceAssembly = Assembly.Load("Resources");
ResourceManager rm = new ResourceManager("MyResources", resourceAssembly);
string localizedText = rm.GetString("WelcomeMessage");

四、注意事项与最佳实践

1. 依赖项管理

  • LoadFrom:适合大多数场景,依赖项会自动加载(需确保依赖项在路径中)。
  • LoadFile:需手动处理依赖项,适合需要隔离加载或加载多个同名程序集的场景。

2. 安全性

  • 确保动态加载的程序集来源可信,避免加载恶意代码。
  • 使用 AppDomain 隔离加载程序集,限制其权限(如沙箱环境)。

3. 性能优化

  • 缓存 MethodInfoConstructorInfo 等反射对象,避免频繁反射调用。
  • 对于高频调用的方法,考虑使用 System.Linq.Expressions 生成委托代替 Invoke

4. 卸载程序集

C# 中无法直接卸载单个程序集,需通过卸载整个 AppDomain 实现:

// 创建新 AppDomain 并加载程序集
AppDomain domain = AppDomain.CreateDomain("PluginDomain");
domain.Load("MyAssembly");

// 卸载 AppDomain 以释放程序集
AppDomain.Unload(domain);

五、完整示例:动态加载并调用 DLL

using System;
using System.IO;
using System.Reflection;

class Program
{
    static void Main()
    {
        // 注册依赖项加载事件
        AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;

        // 动态加载主程序集
        string mainDllPath = @"C:\MainAssembly.dll";
        Assembly mainAssembly = Assembly.LoadFile(mainDllPath);

        // 获取类型并创建实例
        Type mainType = mainAssembly.GetType("MainNamespace.MainClass");
        object mainInstance = Activator.CreateInstance(mainType);

        // 调用方法
        MethodInfo method = mainType.GetMethod("Run");
        method.Invoke(mainInstance, null);
    }

    private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        // 手动加载依赖项
        string dependencyPath = Path.Combine(@"C:\Dependencies", new AssemblyName(args.Name).Name + ".dll");
        return File.Exists(dependencyPath) ? Assembly.LoadFile(dependencyPath) : null;
    }
}

六、总结

动态加载程序集是 C# 实现灵活架构的关键技术,适用于插件系统、模块化设计和运行时扩展等场景。通过合理选择 Assembly.LoadLoadFromLoadFile,结合依赖项管理和性能优化,可以高效实现动态加载需求。同时,需注意安全性和资源隔离,确保应用程序的稳定性和可控性。

以上就是C#动态加载程序集的全攻略的详细内容,更多关于C#动态加载程序集的资料请关注脚本之家其它相关文章!

相关文章

  • c#泛型学习详解 创建线性链表

    c#泛型学习详解 创建线性链表

    Visual C# 2.0 的一个最受期待的(或许也是最让人畏惧)的一个特性就是对于泛型的支持。这篇文章将告诉你泛型用来解决什么样的问题,以及如何使用它们来提高你的代码质量,还有你不必恐惧泛型的原因
    2014-01-01
  • C#数据库操作类AccessHelper实例

    C#数据库操作类AccessHelper实例

    这篇文章主要介绍了C#数据库操作类AccessHelper实例,可实现针对access数据库的各种常见操作,非常具有实用价值,需要的朋友可以参考下
    2014-10-10
  • C#读取word中表格数据的方法实现

    C#读取word中表格数据的方法实现

    本文主要介绍了C#读取word中表格数据的方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • C# http系列之以form-data方式上传多个文件及键值对集合到远程服务器

    C# http系列之以form-data方式上传多个文件及键值对集合到远程服务器

    这篇文章主要介绍了C# http系列之以form-data方式上传多个文件及键值对集合到远程服务器,需要的朋友可以参考下
    2019-08-08
  • C#实现在服务器端裁剪图片的方法

    C#实现在服务器端裁剪图片的方法

    这篇文章主要介绍了C#实现在服务器端裁剪图片的方法,涉及C#操作图片的相关技巧,需要的朋友可以参考下
    2015-04-04
  • C#实现压缩和解压缩的方法示例【Gzip和Zip方式】

    C#实现压缩和解压缩的方法示例【Gzip和Zip方式】

    这篇文章主要介绍了C#实现压缩和解压缩的方法,结合具体实例形式分析了Gzip和Zip两种压缩操作实现方法,需要的朋友可以参考下
    2017-06-06
  • C# 实现绘制PDF嵌套表格案例详解

    C# 实现绘制PDF嵌套表格案例详解

    嵌套表格,顾名思义,就是在一张表格中的特定单元格中再插入一个或者多个表格,本文将为大家介绍C#绘制PDF嵌套表格的代码示例,需要的同学可以参考一下
    2021-11-11
  • C#/VB.NET实现在 Word 中插入水印 

    C#/VB.NET实现在 Word 中插入水印 

    这篇文章主要介绍了C#/VB.NET实现在 Word 中插入水印,水印是指在 Word 文档的背景中以淡色或灰色显示的文本或图像。文章围绕主题展开介绍,需要的朋友可以参考一下
    2022-08-08
  • 一文掌握C# JSON(2023最新整理)

    一文掌握C# JSON(2023最新整理)

    JSON的全称是JavaScript Object Notation,意思是JavaScript对象表示法,它是一种基于文本,独立于语言的轻量级数据交换格式,这篇文章主要介绍了C#中的JSON(2023最新整理),需要的朋友可以参考下
    2023-05-05
  • winform 使用Anchor属性进行界面布局的方法详解

    winform 使用Anchor属性进行界面布局的方法详解

    这篇文章主要介绍了winform 使用Anchor属性进行界面布局的方法,有需要的朋友可以参考一下
    2013-12-12

最新评论