跳到主要内容

C# 动态加载程序集

介绍

在 C# 中,程序集(Assembly)是包含编译后代码的单元,通常以 .dll.exe 文件的形式存在。动态加载程序集是指在运行时根据需要加载程序集,而不是在编译时静态引用。这种技术常用于插件系统、模块化应用程序以及需要灵活加载代码的场景。

通过动态加载程序集,你可以在不重新编译主应用程序的情况下扩展其功能。本文将逐步讲解如何在 C# 中实现动态加载程序集,并通过实际案例展示其应用。

动态加载程序集的基本概念

什么是程序集?

程序集是 .NET 应用程序的基本构建块,包含编译后的代码、元数据和资源。每个程序集都有一个唯一的名称(称为程序集名称),并且可以包含一个或多个模块。

动态加载程序集的场景

动态加载程序集的常见场景包括:

  • 插件系统:允许第三方开发者通过插件扩展应用程序的功能。
  • 模块化应用程序:根据需要加载不同的功能模块,减少启动时间和内存占用。
  • 热更新:在不重启应用程序的情况下更新部分功能。

动态加载程序集的核心类

在 C# 中,动态加载程序集的核心类是 System.Reflection.Assembly。通过 Assembly 类,你可以加载程序集、获取类型信息、创建实例以及调用方法。

动态加载程序集的实现

1. 加载程序集

要动态加载程序集,可以使用 Assembly.LoadFromAssembly.LoadFile 方法。以下是使用 Assembly.LoadFrom 加载程序集的示例:

csharp
using System;
using System.Reflection;

class Program
{
static void Main()
{
// 加载程序集
Assembly assembly = Assembly.LoadFrom("MyLibrary.dll");

// 获取程序集中的所有类型
Type[] types = assembly.GetTypes();

foreach (Type type in types)
{
Console.WriteLine(type.FullName);
}
}
}

输出示例:

MyLibrary.MyClass
MyLibrary.MyOtherClass

2. 创建实例并调用方法

加载程序集后,你可以通过反射创建类型的实例并调用其方法。以下是一个示例:

csharp
using System;
using System.Reflection;

class Program
{
static void Main()
{
// 加载程序集
Assembly assembly = Assembly.LoadFrom("MyLibrary.dll");

// 获取类型
Type myClassType = assembly.GetType("MyLibrary.MyClass");

// 创建实例
object myClassInstance = Activator.CreateInstance(myClassType);

// 获取方法
MethodInfo myMethod = myClassType.GetMethod("MyMethod");

// 调用方法
myMethod.Invoke(myClassInstance, null);
}
}

假设 MyLibrary.dll 中的 MyClass 定义如下:

csharp
namespace MyLibrary
{
public class MyClass
{
public void MyMethod()
{
Console.WriteLine("Hello from MyMethod!");
}
}
}

输出示例:

Hello from MyMethod!

3. 处理依赖项

动态加载程序集时,可能会遇到依赖项问题。如果加载的程序集依赖于其他程序集,你需要确保这些依赖项在运行时可用。可以通过 AppDomain.CurrentDomain.AssemblyResolve 事件来处理未找到的程序集。

csharp
using System;
using System.Reflection;

class Program
{
static void Main()
{
AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;

// 加载程序集
Assembly assembly = Assembly.LoadFrom("MyLibrary.dll");

// 其他代码...
}

static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
{
// 处理未找到的程序集
Console.WriteLine($"Attempting to resolve: {args.Name}");
return null; // 返回 null 表示无法解析
}
}

实际案例:插件系统

假设你正在开发一个支持插件的应用程序。你可以通过动态加载程序集来实现插件系统。

插件接口

首先,定义一个插件接口:

csharp
public interface IPlugin
{
void Execute();
}

插件实现

然后,创建一个插件实现:

csharp
public class MyPlugin : IPlugin
{
public void Execute()
{
Console.WriteLine("MyPlugin is executing!");
}
}

主应用程序

在主应用程序中,动态加载插件并调用其方法:

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

class Program
{
static void Main()
{
string pluginPath = "Plugins/MyPlugin.dll";

if (File.Exists(pluginPath))
{
// 加载插件程序集
Assembly pluginAssembly = Assembly.LoadFrom(pluginPath);

// 获取插件类型
Type pluginType = pluginAssembly.GetType("MyPlugin");

// 创建插件实例
IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType);

// 调用插件方法
plugin.Execute();
}
else
{
Console.WriteLine("Plugin not found!");
}
}
}

输出示例:

MyPlugin is executing!

总结

动态加载程序集是 C# 中一项强大的技术,适用于插件系统、模块化应用程序等场景。通过 Assembly 类和反射,你可以在运行时加载程序集、创建实例并调用方法。本文介绍了动态加载程序集的基本概念、实现方法以及一个实际案例。

附加资源与练习

通过实践和深入学习,你将掌握动态加载程序集的核心技术,并能够灵活应用于实际项目中。