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

发布于 2025-01-04 10:44:37 字数 1098 浏览 3 评论 0原文

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

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

视图代码(MVC 应用程序程序集):

<nav>
   <ul id="menu">
      @foreach(var item in new MvcHelper().GetControllerNames())
      {
         @Html.ActionMenuItem(
              (string)HttpContext.GetGlobalResourceObject("StringsResourse", item), "Index",
              item)
      }
   </ul>
</nav>

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

public class MvcHelper
{
    public  List<string> GetControllerNames()
    {
        var controllerNames = new List<string>();
        GetSubClasses<Controller>().ForEach(
            type => controllerNames.Add(type.Name));
        return controllerNames;
    }

    private static List<Type> GetSubClasses<T>()
    {
        return Assembly.GetCallingAssembly().GetTypes().Where(
            type => type.IsSubclassOf(typeof(T))).ToList();
    }
}

我在这里做错了什么?

In my ASP.NET MVC app I'm using a small helper to iterate through all the controllers.
This helper is located at a different assembly than my MVC app and I'm referencing to it.

The problem is, that when calling the Assembly.GetCallingAssembly() method in the helper, it doesn't returns the MVC app assembly, but it returns the helper assembly instead.
This is not what I'm expecting to get, because all my controllers are living in the MVC app assembly and I need to reflect it.

The view code(MVC app assembly):

<nav>
   <ul id="menu">
      @foreach(var item in new MvcHelper().GetControllerNames())
      {
         @Html.ActionMenuItem(
              (string)HttpContext.GetGlobalResourceObject("StringsResourse", item), "Index",
              item)
      }
   </ul>
</nav>

The Helper code(independent assembly):

public class MvcHelper
{
    public  List<string> GetControllerNames()
    {
        var controllerNames = new List<string>();
        GetSubClasses<Controller>().ForEach(
            type => controllerNames.Add(type.Name));
        return controllerNames;
    }

    private static List<Type> GetSubClasses<T>()
    {
        return Assembly.GetCallingAssembly().GetTypes().Where(
            type => type.IsSubclassOf(typeof(T))).ToList();
    }
}

What am I doing wrong here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

难忘№最初的完美 2025-01-11 10:44:37

我在这里做错了什么?

没有什么。您可能忽略了一个事实:Razor 视图由 ASP.NET 运行时编译为单独的程序集。这些程序集是动态的。它们与 ASP.NET MVC 应用程序集无关。由于您在视图中调用帮助程序,Assembly.GetCallingAssembly() 方法将返回如下内容:

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

如果您想获取所有控制器,为什么不直接循环遍历所有引用的程序集并查找派生类型来自控制器?您可以使用 AppDomain.CurrentDomain.GetAssemblies()< /code>方法。然后,对于每个程序集,只需 GetTypes() 并进行过滤:

public class MvcHelper
{
    private static List<Type> GetSubClasses<T>()
    {
        return AppDomain
            .CurrentDomain
            .GetAssemblies()
            .SelectMany(
                a => a.GetTypes().Where(type => type.IsSubclassOf(typeof(T)))
            ).ToList();
    }

    public List<string> GetControllerNames()
    {
        var controllerNames = new List<string>();
        GetSubClasses<Controller>().ForEach(
            type => controllerNames.Add(type.Name));
        return controllerNames;
    }
}

What am I doing wrong here?

Nothing. You are probably missing the fact that Razor views are compiled as separate assemblies by the ASP.NET runtime. Those assemblies are dynamic. They have nothing to do with your ASP.NET MVC application assembly. And since you are calling the helper in your view the Assembly.GetCallingAssembly() method will return something like this:

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

If you want to get all controllers why not just loop through all referenced assemblies and look for types deriving from Controller? You could use the AppDomain.CurrentDomain.GetAssemblies() method for this. Then for each assembly just GetTypes() and filter upon:

public class MvcHelper
{
    private static List<Type> GetSubClasses<T>()
    {
        return AppDomain
            .CurrentDomain
            .GetAssemblies()
            .SelectMany(
                a => a.GetTypes().Where(type => type.IsSubclassOf(typeof(T)))
            ).ToList();
    }

    public List<string> GetControllerNames()
    {
        var controllerNames = new List<string>();
        GetSubClasses<Controller>().ForEach(
            type => controllerNames.Add(type.Name));
        return controllerNames;
    }
}
掩于岁月 2025-01-11 10:44:37

来自 GetCallingAssembly MSDN 文档< /a>:

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

在您的情况下,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 所属的程序集。

From the GetCallingAssembly MSDN docs:

Returns the Assembly of the method that invoked the currently executing method.

In your case, GetSubClasses is called by GetControllerNames in the same object so it should be returning the helper assembly.

Edit:

From the Remarks on the MSDN docs:

If the method that calls the GetCallingAssembly method is expanded
inline by the just-in-time (JIT) compiler, or if its caller is
expanded inline, the assembly that is returned by GetCallingAssembly
may differ unexpectedly. For example, consider the following methods
and assemblies:

Method M1 in assembly A1 calls GetCallingAssembly.

Method M2 in assembly A2 calls M1.

Method M3 in assembly A3 calls M2.

When M1 is not inlined, GetCallingAssembly returns A2. When M1 is
inlined, GetCallingAssembly returns A3. Similarly, when M2 is not
inlined, GetCallingAssembly returns A2. When M2 is inlined,
GetCallingAssembly returns A3.

So assuming the GetSubClasses isn't inlined, it should be returning the Assembly which GetControllerNames belongs to.

俏︾媚 2025-01-11 10:44:37

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

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

I believe GetCallingAssembly is working - the method that calls GetSubClasses is within your MvcHelper module (and assembly) rather than the MVC app itself. If you invoke Assembly.GetCallingAssembly directly within GetControllerNames you may find you get a different result.

Also note that the behaviour of GetCallingAssembly can vary depending on whether methods are inlined or not - see http://msdn.microsoft.com/en-us/library/system.reflection.assembly.getcallingassembly.aspx

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文