答案:.NET Reflection允许程序在运行时动态加载类型、调用方法和访问属性,主要通过Assembly.LoadFrom等方法加载程序集,再使用GetType或GetTypes获取类型信息,并结合Activator.CreateInstance创建实例,常用于插件化架构、DI容器、ORM框架等场景。

.NET的Reflection是一种强大的机制,它允许程序在运行时检查自身的元数据(类型信息、成员信息等)并动态地创建对象、调用方法或访问属性。简单来说,它让你的代码能够“自省”,理解和操作自身结构,而不仅仅是执行预先编译好的指令。
要动态加载类型,我们通常会从加载程序集(Assembly)开始。程序集是.NET应用程序的基本部署单元,包含了编译后的代码和元数据。一旦程序集被加载到内存中,你就可以通过Reflection来探索它内部的类型了。
加载程序集有几种常见的方式,每种都有其适用场景和需要注意的地方:
Assembly.Load(string assemblyName)
"MyLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
Assembly.LoadFrom(string assemblyFile)
Assembly.LoadFrom("C:\Plugins\MyPlugin.dll")LoadFrom
Assembly.LoadFile(string path)
Assembly.Load(byte[] rawAssembly)
一旦程序集加载成功,你就可以开始获取其中的类型了:
assembly.GetType("MyNamespace.MyClass")assembly.GetTypes()
获取到
Type
Activator.CreateInstance(type)
type.GetMethod("MethodName")type.GetProperty("PropertyName")MethodInfo.Invoke
PropertyInfo.GetValue/SetValue
using System;
using System.Reflection;
using System.Linq; // For LINQ extension methods like FirstOrDefault
// 假设我们有一个名为 "MyPlugin.dll" 的程序集,其中包含一个实现了 IPlugin 接口的类。
// IPlugin 接口定义:
// public interface IPlugin
// {
// string Name { get; }
// void Execute();
// }
// 示例:动态加载并执行一个插件
public class ReflectionExample
{
public static void Main(string[] args)
{
string pluginPath = "MyPlugin.dll"; // 假设MyPlugin.dll在应用程序的运行目录下
try
{
// 1. 尝试加载程序集
// 我个人倾向于 LoadFrom,因为它能处理相对路径,也比较直观
Assembly pluginAssembly = Assembly.LoadFrom(pluginPath);
Console.WriteLine($"程序集 '{pluginAssembly.FullName}' 已成功加载。");
// 2. 在加载的程序集中查找实现了 IPlugin 接口的类型
// 这里的判断逻辑是:类型是接口 IPlugin 的子类/实现,并且它本身不是接口或抽象类
Type pluginType = pluginAssembly.GetTypes()
.FirstOrDefault(t => typeof(IPlugin).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract);
if (pluginType != null)
{
Console.WriteLine($"找到插件类型: {pluginType.FullName}");
// 3. 创建该类型的一个实例
// Activator.CreateInstance 会调用类型的无参数构造函数
IPlugin pluginInstance = (IPlugin)Activator.CreateInstance(pluginType);
// 4. 调用插件的方法
Console.WriteLine($"插件名称: {pluginInstance.Name}");
pluginInstance.Execute();
}
else
{
Console.WriteLine($"在程序集 '{pluginPath}' 中未找到实现了 IPlugin 接口的有效类型。");
}
}
catch (FileNotFoundException)
{
Console.WriteLine($"错误:未找到程序集文件 '{pluginPath}'。请确保它在正确的路径。");
}
catch (BadImageFormatException)
{
Console.WriteLine($"错误:'{pluginPath}' 不是有效的.NET程序集。");
}
catch (Exception ex)
{
Console.WriteLine($"加载或执行插件时发生未知错误: {ex.Message}");
// 在实际应用中,这里可能需要更详细的日志记录 ex.ToString()
}
Console.ReadKey();
}
}
// 假设 MyPlugin.dll 内部的代码结构
// namespace MyPluginNamespace
// {
// public interface IPlugin
// {
// string Name { get; }
// void Execute();
// }
// public class SimplePlugin : IPlugin
// {
// public string Name => "我的简单插件";
// public void Execute()
// {
// Console.WriteLine("插件:正在执行一些任务...");
// }
// }
// }我记得刚开始接触Reflection的时候,觉得它有点像编程里的“X光机”,能让你看到代码内部的骨架和脏器,这感觉挺奇妙的。我们之所以需要它,主要是为了实现一些在编译时无法确定,或者需要高度灵活性的场景。
[TestMethod]
[Fact]
RealProxy
DynamicProxy
说实话,刚开始用Reflection的时候,确实踩过不少坑,最常见的就是运行时抛出各种
MissingMethodException
TargetInvocationException
MethodInfo.Invoke
Type
MethodInfo
PropertyInfo
DynamicMethod
DynamicMethod
TargetInvocationException
MissingMethodException
TypeLoadException
AssemblyLoadContext
Assembly.LoadFrom
Assembly.LoadFile
Reflection在现代.NET应用中无处不在,尽管我们可能没有直接编写Reflection代码,但我们使用的许多框架和库都在底层大量依赖它。
services.AddTransient<IMyService, MyServiceImplementation>()
MyServiceImplementation
[Test]
[Fact]
[Required]
[Range(min, max)]
想象一下,如果你在做一个需要用户自定义行为的桌面应用,比如一个报表生成器,用户可以自己编写一些逻辑来处理数据。这时候,Reflection就是你的得力助手,你不需要每次都重新编译你的主程序。你只需要提供一个接口,让用户编写实现了这个接口的DLL,你的应用就能在运行时加载并执行这些自定义逻辑。
以上就是.NET的Reflection是什么?如何动态加载类型?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号