使用Assembly.GetCallingAssembly()不返回调用程序集

在我的ASP.NET MVC应用程序中,我使用一个小助手来遍历所有控制器。 这个帮助器位于与我的MVC应用程序不同的程序集中,我正在引用它。

问题是,当在helper中调用Assembly.GetCallingAssembly()方法时,它不会返回MVC app程序集,而是返回帮助程序集。 这不是我期望得到的,因为我的所有控制器都存在于MVC app程序集中,我需要反映它。

视图代码(MVC app程序集):

 

帮助程序代码(独立程序集):

 public class MvcHelper { public List GetControllerNames() { var controllerNames = new List(); GetSubClasses().ForEach( type => controllerNames.Add(type.Name)); return controllerNames; } private static List GetSubClasses() { return Assembly.GetCallingAssembly().GetTypes().Where( type => type.IsSubclassOf(typeof(T))).ToList(); } } 

我在这做错了什么?

我在这做错了什么?

没有。 您可能错过了Razor视图由ASP.NET运行时编译为单独的程序集的事实。 那些集会是动态的。 它们与ASP.NET MVC应用程序程序集无关。 因为你在视图中调用帮助器,所以Assembly.GetCallingAssembly()方法将返回如下内容:

 App_Web_fqxdopd5, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null 

如果您想获得所有控制器,为什么不只是遍历所有引用的程序集并查找从Controller派生的类型? 您可以使用AppDomain.CurrentDomain.GetAssemblies()方法。 然后对于每个程序集只需GetTypes()并过滤:

 public class MvcHelper { private static List GetSubClasses() { return AppDomain .CurrentDomain .GetAssemblies() .SelectMany( a => a.GetTypes().Where(type => type.IsSubclassOf(typeof(T))) ).ToList(); } public List GetControllerNames() { var controllerNames = new List(); GetSubClasses().ForEach( type => controllerNames.Add(type.Name)); return controllerNames; } } 

GetCallingAssembly MSDN文档 :

返回调用当前正在执行的方法的方法的程序集。

在您的情况下, GetSubClasses由同一对象中的GetControllerNames调用,因此它应该返回帮助程序集。

编辑:

来自MSDN文档的备注:

如果调用GetCallingAssembly方法的方法由实时(JIT)编译器内联扩展,或者其调用者是内联扩展的,则GetCallingAssembly返回的程序集可能会出乎意料地不同。 例如,请考虑以下方法和程序集:

程序集A1中的方法M1调用GetCallingAssembly。

组件A2中的方法M2调用M1。

组件A3中的方法M3调用M2。

当M1未内联时,GetCallingAssembly返回A2。 当M1内联时,GetCallingAssembly返回A3。 类似地,当M2未内联时,GetCallingAssembly返回A2。 当内联M2时,GetCallingAssembly返回A3。

因此,假设GetSubClasses没有内联,它应该返回GetControllerNames所属的Assembly。

我相信GetCallingAssembly正在运行 – 调用GetSubClasses的方法在你的MvcHelper模块(和程序集)中,而不是MVC应用程序本身。 如果直接在GetControllerNames调用Assembly.GetCallingAssembly ,您可能会发现得到的结果不同。

另请注意, GetCallingAssembly的行为可能会有所不同,具体取决于方法是否内联 – 请参阅http://msdn.microsoft.com/en-us/library/system.reflection.assembly.getcallingassembly.aspx