【发布时间】:2010-08-23 22:34:30
【问题描述】:
我有一个引导程序,它查看 ASP.NET MVC 应用程序中的所有程序集以查找实现 IBootstrapperTask 接口的类型,然后将它们注册到 IOC 容器。这个想法是您可以将您的 IBootstrapperTasks 放在任何地方,并按照您的喜好组织您的项目。
引导程序代码:
public class Bootstrapper
{
static Bootstrapper()
{
Type bootStrapperType = typeof(IBootstrapperTask);
IList<Assembly> assemblies = AppDomain.CurrentDomain.GetAssemblies();
List<Type> tasks = new List<Type>();
foreach (Assembly assembly in assemblies)
{
var types = from t in assembly.GetTypes()
where bootStrapperType.IsAssignableFrom(t)
&& !t.IsInterface && !t.IsAbstract
select t;
tasks.AddRange(types);
}
foreach (Type task in tasks)
{
if (!IocHelper.Container().Kernel.HasComponent(task.FullName))
{
IocHelper.Container().AddComponentLifeStyle(
task.FullName, task, LifestyleType.Transient);
}
}
}
public static void Run()
{
// Get all registered IBootstrapperTasks, call Execute() method
}
}
完整构建后,AppDomain.CurrentDomain.GetAssemblies() 返回我的解决方案中的所有程序集(包括所有 GAC 的程序集,但这不会打扰我)。
但是,如果 AppDomain 重新启动,或者我“反弹”Web.Config 文件(添加空格并保存),静态构造函数会再次运行,但是当调用 AppDomain.CurrentDomain.GetAssemblies() 时,大多数程序集丢失了,包括包含我的 IBootstrapperTask 类型的那个。
如何解决这个问题?我想我可以 System.IO /bin 目录并手动加载其中的所有 DLL,但如果可能的话宁愿避免这种情况,或者这是唯一的方法吗?我是否采取了正确的通用方法?
这是一个在 .NET 4.0 上运行的 ASP.NET MVC 2.0 应用程序,我使用内置的 Visual Studio 2010 Cassini Web 服务器和 Windows Server 2008 上的集成管道模式下的 IIS7.0 遇到了这个问题。
编辑:我刚刚看到这篇 SO 帖子 Difference between AppDomain.GetAssemblies and BuildManager.GetReferencedAssemblies,它说 AppDomain 仅在需要时加载程序集(例如,当第一次调用该程序集的方法/类时) .我想这可以解释为什么 AppDomain.CurrentDomain.GetAssemblies() 上缺少程序集,因为 Bootstrapper 很早就运行了。
我注意到如果我在引导程序之前从缺少的程序集中调用了“某物”,例如:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
MyApp.MissingAssembly.SomeClass someClass =
new MyApp.MissingAssembly.SomeClass();
Bootstrapper.Run();
}
}
...它似乎解决了这个问题,但它是一个有点黑客。
【问题讨论】:
-
很好的问答!参观了你的博客——你写了一些好东西。
标签: c# asp.net asp.net-mvc reflection assemblies