ResolveEventArgs args){ // 根据加载失败程序集的名字找到该程序集并返回 if (args.N

时间:2021-12-04 06:24:34

我们知道反射是 依赖注入 模式的根本,依赖注入要求只在项目中引用界说接口的措施集,而不引用接口实现类的措施集,因为接口实现类的措施集应该是通过反射来动态加载的,这样才华保证接口与其实现类之间的松耦合。可是有时候我们使用反射动态加载措施集的时候会掉败,因为除非我们手动将接口实现类的措施集放在项目生成后的bin目录下,或者是在GAC中,否者.Net Framework并不知道该到哪里去寻找接口实现类的dll措施集文件。幸运的是我们如果使用 AppDomain.CurrentDomain.AssemblyResolve事件,就可以通过C#代码来自界说措施集加载逻辑,当C#反射解析措施集掉败的时候,通过执行自界说措施集加载逻辑来找到相应的措施集dll文件。

例如此刻我们界说了一个普通的C#类库项目叫MessageDisplay,如下图所示

里面只包罗了一个C#类MessageDisplayHelper.cs文件,MessageDisplayHelper.cs代码如下:

using System; namespace MessageDisplay { public class MessageDisplayHelper { public string Display() { return "This is a message!"; } } }

然后我们界说一个C#控制台措施叫AssemblyResolverConsle:

ResolveEventArgs args){ // 根据加载失败程序集的名字找到该程序集并返回 if (args.N

在这个控制台措施中我们不直接引用MessageDisplay措施集,而是使用反射加载措施集MessageDisplay,然后使用反射动态结构MessageDisplayHelper类。由于我们没有在控制台措施AssemblyResolverConsle中直接引用MessageDisplay措施集,,所以在挪用Assembly.Load要领动态加载措施集的时候会掉败,从而触发AppDomain.CurrentDomain.AssemblyResolve事件。AssemblyResolverConsle控制台措施的Program.cs文件代码如下:

using System; using System.Reflection; namespace AssemblyResolverConsle { class Program { static void Main(string[] args) { //当措施集通过反射加载掉败的时候会触发AssemblyResolve事件,这里注册AssemblyResolve事件的措置惩罚惩罚函数为CurrentDomain_AssemblyResolve AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; //这里通过挪用Assembly.Load要领反射加载MessageDisplay措施集会掉败,因为本项目中没有引用该措施集,而且MessageDisplay措施集的dll文件也不在本项目生成的bin目录下,也不在GAC中。所以这里会触发AssemblyResolve事件,挪用措置惩罚惩罚函数CurrentDomain_AssemblyResolve来测验考试执行自界说措施集加载逻辑,然后措置惩罚惩罚函数CurrentDomain_AssemblyResolve会为这里的Assembly.Load要领返回MessageDisplay.dll措施集 var messageDisplayAssembly = Assembly.Load("MessageDisplay"); //使用反射动态挪用MessageDisplayHelper类的结构函数 var messageDisplayHelper = messageDisplayAssembly.CreateInstance("MessageDisplay.MessageDisplayHelper"); Console.WriteLine(messageDisplayHelper.ToString()); Console.ReadLine(); } /// <summary> /// AssemblyResolve事件的措置惩罚惩罚函数,该函数用来自界说措施集加载逻辑 /// </summary> /// <param>事件引起源</param> /// <param>事件参数,从该参数中可以获取加载掉败的措施集的名称</param> /// <returns></returns> private static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { //按照加载掉败措施集的名字找到该措施集并返回 if (args.Name == "MessageDisplay") { //我们自界说的措施集加载逻辑知道MessageDisplay措施集在C:\AssemblyResolverConsle\Reference\MessageDisplay.dll这个路径下,所以这里加载这个路径下的dll文件作为AssemblyResolve事件措置惩罚惩罚函数的返回值 return Assembly.LoadFile(@"C:\AssemblyResolverConsle\Reference\MessageDisplay.dll"); } //如果AssemblyResolve事件的措置惩罚惩罚函数返回null,说明AssemblyResolve事件的措置惩罚惩罚函数也无法找到加载掉败的措施集,那么整个措施就会抛出异常报错 return null; } } }