Assembly类负责程序集加载与管理,提供Load、LoadFrom、ReflectionOnlyLoadFrom等方法加载程序集,通过反射可调用其类型和方法,但需注意性能损耗;加载失败常见原因为文件缺失、依赖缺失、版本冲突、权限不足或程序集损坏,可通过配置绑定重定向解决版本问题;.NET Framework中无法单独卸载程序集,需通过卸载应用程序域实现,但会清除域内所有对象,适用于插件系统等场景。
.NET的Assembly类主要负责程序集的加载、反射和管理。简单来说,它代表了.NET应用程序的基本部署单元,包含了编译好的代码、资源和元数据。加载程序集,其实就是让你的程序知道有哪些类型、方法可以调用。
解决方案
Assembly类提供多种加载程序集的方法,最常用的包括:
-
Assembly.Load(AssemblyName assemblyName): 通过程序集名称加载。你需要提供程序集的完整名称,包括名称、版本、公钥标记等。 这通常用于加载已知程序集。
AssemblyName assemblyName = new AssemblyName("MyLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); Assembly assembly = Assembly.Load(assemblyName);
-
Assembly.LoadFrom(string assemblyFile): 通过程序集文件路径加载。 这种方式直接指定程序集文件的位置,更加灵活。
Assembly assembly = Assembly.LoadFrom("C:MyLibrariesMyLibrary.dll");
-
Assembly.ReflectionOnlyLoadFrom(string assemblyFile): 只加载程序集的元数据,不执行代码。 这在需要检查程序集结构但不需要运行代码时非常有用。
Assembly assembly = Assembly.ReflectionOnlyLoadFrom("C:MyLibrariesMyLibrary.dll");
-
Assembly.Load(byte[] rawAssembly): 从字节数组加载程序集。 这允许你从内存中加载程序集,例如从数据库或网络流中读取。
byte[] assemblyBytes = File.ReadAllBytes("C:MyLibrariesMyLibrary.dll"); Assembly assembly = Assembly.Load(assemblyBytes);
-
Assembly.GetExecutingAssembly(): 获取当前正在执行的程序集。
Assembly executingAssembly = Assembly.GetExecutingAssembly();
选择哪种加载方式取决于你的具体需求。 如果你知道程序集的名称,Assembly.Load 是一个不错的选择。如果只需要加载元数据,Assembly.ReflectionOnlyLoadFrom 是最佳选择。 如果你需要从文件加载,Assembly.LoadFrom 是最直接的。
动态加载程序集后如何使用其中的类型和方法?
一旦程序集被加载,你就可以使用反射来访问其中的类型和方法。 反射允许你在运行时检查和操作程序集的元数据。
// 假设已经加载了程序集 assembly Type myType = assembly.GetType("MyLibrary.MyClass"); // 获取类型 if (myType != null) { object instance = Activator.CreateInstance(myType); // 创建实例 MethodInfo myMethod = myType.GetMethod("MyMethod"); // 获取方法 if (myMethod != null) { object result = myMethod.Invoke(instance, null); // 调用方法 Console.WriteLine(result); } }
需要注意的是,反射操作的性能相对较低,因为它涉及到运行时的类型查找和方法调用。 因此,应该谨慎使用,并尽量避免在性能敏感的代码中使用。
程序集加载失败的常见原因及解决方法?
程序集加载失败可能由多种原因引起,最常见的是:
-
程序集找不到: 可能是程序集文件不存在,或者程序集的路径不正确。 确保程序集文件存在于指定路径,并且应用程序有权访问该文件。
-
依赖项缺失: 程序集依赖于其他程序集,但这些依赖项没有被正确加载。 检查程序集的依赖项,并确保所有依赖项都存在于应用程序的加载路径中。 可以使用 fuslogvw.exe (程序集绑定日志查看器)来诊断程序集加载失败的原因。
-
版本冲突: 应用程序加载了多个具有相同名称但不同版本的程序集。 这可能导致版本冲突,从而导致程序集加载失败。 可以使用程序集重定向(在 app.config 或 web.config 文件中配置)来解决版本冲突。
<configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="MyLibrary" publicKeyToken="b77a5c561934e089" culture="neutral" /> <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0" /> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
-
权限问题: 应用程序没有足够的权限来加载程序集。 确保应用程序具有读取程序集文件的权限,以及执行程序集代码的权限。
-
程序集损坏: 程序集文件可能已损坏。尝试重新编译程序集,或者从可靠的来源获取程序集文件。
调试程序集加载问题可能比较棘手,但通过仔细检查错误消息、使用程序集绑定日志查看器以及了解常见的加载失败原因,可以有效地解决这些问题。
如何卸载已加载的程序集?
.NET Framework 不提供直接卸载单个程序集的方法。 一旦程序集被加载到应用程序域中,它就会一直存在,直到应用程序域被卸载。 这听起来有点极端,但这是设计使然。
要卸载程序集,你需要卸载包含该程序集的应用程序域。 应用程序域提供了一个隔离的环境,允许你加载和卸载程序集,而不会影响其他应用程序域。
// 创建一个新的应用程序域 appDomain domain = AppDomain.CreateDomain("MyDomain"); // 加载程序集到新的应用程序域 Assembly assembly = domain.Load("MyLibrary"); // ... 使用程序集 ... // 卸载应用程序域 AppDomain.Unload(domain);
需要注意的是,卸载应用程序域会导致其中所有对象被销毁。 因此,在卸载应用程序域之前,你需要确保所有不再需要的资源都已被释放。 此外,跨应用程序域的通信需要使用远程处理技术,这会增加一定的复杂性。
虽然卸载程序集不是一个常见的操作,但在某些情况下,例如插件系统或动态代码生成,它可能是必要的。 应用程序域提供了一种相对安全和可靠的方式来管理程序集的生命周期。