在C#的实际开发中,动态加载程序集是一项非常实用的技术,尤其在需要实现插件化架构、热更新功能或者按需加载模块的场景下,掌握这项技术能大幅提升程序的灵活性。下面我们就一步步讲解如何实现动态加载程序集并获取相关信息。

动态加载程序集的基础方法
C#中动态加载程序集主要依靠System.Reflection.Assembly类提供的静态方法,最常用的是LoadFrom和Load方法,两者的使用场景有所区别。
LoadFrom方法可以直接传入程序集的文件路径,加载指定路径下的程序集,适合加载本地磁盘上的程序集文件。下面是一个基础的使用示例:
using System;
using System.Reflection;
class Program
{
static void Main()
{
// 要加载的程序集路径,这里替换为实际的dll路径
string assemblyPath = @"D:\TestLibrary.dll";
try
{
// 动态加载程序集
Assembly assembly = Assembly.LoadFrom(assemblyPath);
Console.WriteLine($"程序集加载成功,名称:{assembly.FullName}");
}
catch (Exception ex)
{
Console.WriteLine($"加载程序集失败:{ex.Message}");
}
}
}如果需要加载已经位于应用程序基目录或者私有bin路径下的程序集,也可以使用Assembly.Load方法,传入程序集的名称即可,不需要完整路径。
获取程序集的基础信息
程序集加载完成后,我们可以通过Assembly实例的属性获取各类基础信息,比如程序集的全名、版本、公钥标记、自定义特性等。
常用的属性包括:
- FullName:获取程序集的全名,包含名称、版本、文化、公钥标记等信息
- Location:获取程序集文件的完整路径
- GetCustomAttributes:获取程序集上定义的所有自定义特性
- GetTypes:获取程序集内定义的所有类型
下面是通过加载后的程序集获取这些信息的示例代码:
using System;
using System.Reflection;
using System.Linq;
class Program
{
static void Main()
{
string assemblyPath = @"D:\TestLibrary.dll";
try
{
Assembly assembly = Assembly.LoadFrom(assemblyPath);
// 获取程序集全名
Console.WriteLine($"程序集全名:{assembly.FullName}");
// 获取程序集文件路径
Console.WriteLine($"程序集路径:{assembly.Location}");
// 获取程序集版本信息
Version version = assembly.GetName().Version;
Console.WriteLine($"程序集版本:{version}");
// 获取程序集内的所有类型
Type[] types = assembly.GetTypes();
Console.WriteLine($"程序集包含类型数量:{types.Length}");
foreach (Type type in types)
{
Console.WriteLine($"类型名称:{type.FullName},类型类别:{type.IsClass ? "类" : type.IsInterface ? "接口" : "其他"}");
}
}
catch (Exception ex)
{
Console.WriteLine($"操作失败:{ex.Message}");
}
}
}获取类型内部信息
除了程序集本身的信息,我们还可以进一步获取程序集内类型的详细信息,包括类型的属性、方法、字段、事件等。
假设我们加载的程序集中有一个名为UserService的类,下面代码演示如何获取这个类的所有公共方法:
using System;
using System.Reflection;
using System.Linq;
class Program
{
static void Main()
{
string assemblyPath = @"D:\TestLibrary.dll";
try
{
Assembly assembly = Assembly.LoadFrom(assemblyPath);
// 获取指定类型
Type userServiceType = assembly.GetType("TestLibrary.UserService");
if (userServiceType == null)
{
Console.WriteLine("未找到指定类型");
return;
}
// 获取类型的所有公共方法
MethodInfo[] methods = userServiceType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
Console.WriteLine($"UserService类型的公共方法数量:{methods.Length}");
foreach (MethodInfo method in methods)
{
Console.WriteLine($"方法名:{method.Name},返回类型:{method.ReturnType.Name}");
// 获取方法的参数信息
ParameterInfo[] parameters = method.GetParameters();
if (parameters.Length > 0)
{
Console.WriteLine("参数列表:");
foreach (ParameterInfo param in parameters)
{
Console.WriteLine($" 参数名:{param.Name},参数类型:{param.ParameterType.Name}");
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"操作失败:{ex.Message}");
}
}
}注意事项
在使用动态加载程序集时,需要注意几个常见问题:
- 程序集加载后如果没有特殊需求,不会自动卸载,如果需要在运行时卸载程序集,需要将程序集加载到独立的应用程序域中,.NET Core及以上版本可以使用AssemblyLoadContext实现隔离加载和卸载
- 加载程序集时要做好异常处理,避免因为路径错误、程序集损坏、版本不兼容等问题导致程序崩溃
- 如果程序集依赖其他程序集,需要确保依赖的程序集可以被正确加载,否则会抛出加载失败的异常
通过上述方法,我们就可以完整实现C#中动态加载程序集并获取相关信息的需求,在实际开发中可以根据具体场景调整获取信息的范围和深度。