【译】在C#中获取程序集比你想得要困难

某一天我正在写一些反射代码,目的是遍历所有的程序集来查找一个特定的接口,然后在Startup中调用其上的一个方法。看起来这个功能似乎很简单,但是在现实中,却没有一个清晰的,简单的,适合各种情形的方式来获取一个程序集。这篇文章获取对某些人来说非常的枯燥,但是如果我能够帮助哪怕一个人来解决此类问题,那么这篇文章也是值得的。

说真的,由于有多种获取程序集的方法,我将不会说”使用这个方法”。很有可能,对于你的特定的工程来说,也许只有一种方式可以工作,所以依赖其他的方式是毫无意义的。让我们简单的对所有的方式做个测试,然后看看哪一个方法是最合理的。

使用AppDomain.GetAssemblies

你可能会遇到的第一个选项是AppDomain.GetAssemblies。它(看似)加载了在AppDomain中的所有程序集,基本上可以说加载了你项目使用到的每一个程序集。但是却存在着大量的警告。在.NET中程序集是延迟加载到AppDomain中的,它不可能一次性加载所有的程序集,而是等你调用了一个程序集中的方法/类的时候,它才会将它加载进来--也就是即时加载。这是合理的,因为如果你从不使用一个程序集的话,是没有理由加载它的。

但问题是在你调用AppDomain.GetAssemblies()的那个时间点上,如果你并没有调用某个特定的程序集的方法,它便不会被加载。现在如果你要为了Startup方法得到所有的程序集,很有可能你还没有调用到那个程序集,这就意味着它还没有加载到AppDomain,所以便获取不到这个接口方法。

用代码来说:

AppDomain.CurrentDomain.GetAssemblies(); // Does not return SomeAssembly as it hasn‘t been called yet. 
SomeAssembly.SomeClass.SomeMethod();
AppDomain.CurrentDomain.GetAssemblies(); // Will now return SomeAssembly. 

虽然这看起来是一个很有吸引力的选项,但是要知道,对于这个方法来说,时机是一切。

使用AssemblyLoad事件

因为你不能确保当你调用CurrentDomain.GetAssemblies()时所有程序集都被加载了,而实际上当AppDomain加载另一个程序集的时候有一个事件会运行。基本上说,当一个程序集被延迟加载的时候,你可以被通知到。它看起来像是这样:

AppDomain.CurrentDomain.AssemblyLoad += (sender, args) =>
{
    var assembly = args.LoadedAssembly;
};

如果你只是想当程序集加载的时候检查下一些东西,那这或许是一个不错的解决方案,但是这个过程在某个特定的点并不是必然会发生(在你的.NET Core app的Startup.cs类中并不会发生)。

 

【译】在C#中获取程序集比你想得要困难

上一篇:用asp.net+Jquery+Ajax+sqlserver编写的 (英语六级记单词)


下一篇:MySQL中索引注意事项和JDBC的应用