Использование Assembly.GetCallingAssembly () не возвращает вызывающую сборку - PullRequest
5 голосов
/ 11 февраля 2012

В моем приложении 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>

Код Helper (самостоятельная сборка):

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();
    }
}

Что я здесь не так делаю?

Ответы [ 3 ]

15 голосов
/ 11 февраля 2012

Что я здесь не так делаю?

Ничего.Вероятно, вы упускаете тот факт, что представления Razor компилируются как отдельные сборки средой выполнения ASP.NET.Эти сборки являются динамическими.Они не имеют ничего общего с вашей сборкой приложения ASP.NET MVC.И так как вы вызываете помощника по вашему мнению, метод Assembly.GetCallingAssembly() вернет что-то вроде этого:

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

Если вы хотите получить все контроллеры, почему бы просто не перебрать все ссылочные сборки и искать производные типыиз контроллера?Для этого вы можете использовать метод AppDomain.CurrentDomain.GetAssemblies().Тогда для каждой сборки просто 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;
    }
}
1 голос
/ 11 февраля 2012

Из GetCallingAssembly документов MSDN :

Возвращает сборку метода, который вызвал выполняемый в данный момент метод.

В вашем случае GetSubClasses вызывается GetControllerNames в том же объекте, поэтому он должен возвращать вспомогательную сборку.

Edit:

Из замечаний в документах MSDN:

Если метод, вызывающий метод GetCallingAssembly, расширен встроенный компилятором JIT, или его вызывающий встроенная развернутая сборка, возвращаемая GetCallingAssembly может неожиданно отличаться. Например, рассмотрим следующие методы и сборки:

Метод M1 в сборке A1 вызывает GetCallingAssembly.

Метод M2 в сборке A2 вызывает M1.

Метод M3 в сборке A3 вызывает M2.

Когда M1 не встроен, GetCallingAssembly возвращает A2. Когда М1 встроенный, GetCallingAssembly возвращает A3. Точно так же, когда М2 не встроенный, GetCallingAssembly возвращает A2. Когда М2 встроен, GetCallingAssembly возвращает A3.

Таким образом, предполагая, что GetSubClasses не встроен, он должен возвращать сборку, которой принадлежит GetControllerNames.

0 голосов
/ 11 февраля 2012

Я считаю, что GetCallingAssembly работает - метод, который вызывает GetSubClasses, находится внутри вашего модуля MvcHelper (и сборки), а не в самом приложении MVC.Если вы вызываете Assembly.GetCallingAssembly непосредственно в GetControllerNames, вы можете обнаружить, что получаете другой результат.

Также обратите внимание, что поведение GetCallingAssembly может варьироваться в зависимости от того, встроены методы или нет - см. http://msdn.microsoft.com/en-us/library/system.reflection.assembly.getcallingassembly.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...