GetEntryAssembly для веб-приложений

Assembly.GetEntryAssembly () не работает для веб-приложений.

Но … Мне действительно нужно что-то подобное. Я работаю с некоторым глубоко вложенным кодом, который используется как в веб-приложениях, так и в не-веб-приложениях.

Моим текущим решением является просмотр StackTrace, чтобы найти первую вызванную сборку.

///  /// Version of 'GetEntryAssembly' that works with web applications ///  /// The entry assembly, or the first called assembly in a web application public static Assembly GetEntyAssembly() { // get the entry assembly var result = Assembly.GetEntryAssembly(); // if none (ex: web application) if (result == null) { // current method MethodBase methodCurrent = null; // number of frames to skip int framestoSkip = 1; // loop until we cannot got further in the stacktrace do { // get the stack frame, skipping the given number of frames StackFrame stackFrame = new StackFrame(framestoSkip); // get the method methodCurrent = stackFrame.GetMethod(); // if found if ((methodCurrent != null) // and if that method is not excluded from the stack trace && (methodCurrent.GetAttribute(false) == null)) { // get its type var typeCurrent = methodCurrent.DeclaringType; // if valid if (typeCurrent != typeof (RuntimeMethodHandle)) { // get its assembly var assembly = typeCurrent.Assembly; // if valid if (!assembly.GlobalAssemblyCache && !assembly.IsDynamic && (assembly.GetAttribute() == null)) { // then we found a valid assembly, get it as a candidate result = assembly; } } } // increase number of frames to skip framestoSkip++; } // while we have a working method while (methodCurrent != null); } return result; } 

Чтобы обеспечить сборку, мы хотим, чтобы у нас было 3 условия:

  • assembly не находится в GAC
  • assembly не является динамичной
  • assembly не сгенерирована (чтобы избежать временных файлов asp.net

Последняя проблема, с которой я встречаюсь, – это когда базовая страница определена в отдельной сборке. (Я использую ASP.Net MVC, но это будет то же самое с ASP.Net). В этом конкретном случае возвращается отдельная assembly, а не та, которая содержит страницу.

Теперь я ищу:

1) Являются ли достаточными условия проверки моей сборки? (Возможно, я забыл)

2) Есть ли способ, с определенной сборкой кода в временной папке ASP.Net, получить информацию о проекте, который содержит эту страницу / представление? (Думаю, нет, но кто знает …)

Это, кажется, надежный, простой способ получить «запись» или основную сборку для веб-приложения.

Если вы поместите controllerы в отдельный проект, вы можете обнаружить, что базовый class ApplicationInstance не находится в той же сборке, что и ваш проект MVC, содержащий представления, но эта настройка кажется довольно редкой (я упоминаю об этом, потому что я пробовал это настройка в какой-то момент, и некоторое время назад несколько блогов поддержали идею).

  static private Assembly GetWebEntryAssembly() { if (System.Web.HttpContext.Current == null || System.Web.HttpContext.Current.ApplicationInstance == null) { return null; } var type = System.Web.HttpContext.Current.ApplicationInstance.GetType(); while (type != null && type.Namespace == "ASP") { type = type.BaseType; } return type == null ? null : type.Assembly; } 

В моем случае мне нужно было получить «сборку входа» для веб-приложения до того, как System.Web.HttpContext.Current.ApplicationInstance будет инициализирован. Кроме того, мой код должен был работать для различных типов приложений (оконные службы, настольные приложения и т. Д.), И я не люблю загрязнять свой общий код веб-проблемами.

Я создал настраиваемый атрибут уровня сборки, который может быть объявлен в файле AssembyInfo.cs сборки, которую вы хотите обозначить как узел точки входа. Затем вы вызываете статический метод GetEntryAssembly атрибута для получения сборки записи. Если Assembly.GetEntryAssembly возвращает ненулевое значение, которое используется, в противном случае он ищет через загруженные сборки для той, у которой есть пользовательский атрибут. Результат кэшируется в Lazy .

 using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace EntryAssemblyAttributeDemo { ///  /// For certain types of apps, such as web apps,  /// returns null. With the , we can designate /// an assembly as the entry assembly by creating an instance of this attribute, /// typically in the AssemblyInfo.cs file. ///  /// [assembly: EntryAssembly] ///  ///  [AttributeUsage(AttributeTargets.Assembly)] public sealed class EntryAssemblyAttribute : Attribute { ///  /// Lazily find the entry assembly. ///  private static readonly Lazy EntryAssemblyLazy = new Lazy(GetEntryAssemblyLazily); ///  /// Gets the entry assembly. ///  /// The entry assembly. public static Assembly GetEntryAssembly() { return EntryAssemblyLazy.Value; } ///  /// Invoked lazily to find the entry assembly. We want to cache this value as it may /// be expensive to find. ///  /// The entry assembly. private static Assembly GetEntryAssemblyLazily() { return Assembly.GetEntryAssembly() ?? FindEntryAssemblyInCurrentAppDomain(); } ///  /// Finds the entry assembly in the current app domain. ///  /// The entry assembly. private static Assembly FindEntryAssemblyInCurrentAppDomain() { var assemblies = AppDomain.CurrentDomain.GetAssemblies(); var entryAssemblies = new List(); foreach (var assembly in assemblies) { // Note the usage of LINQ SingleOrDefault. The EntryAssemblyAttribute's AttrinuteUsage // only allows it to occur once per assembly; declaring it more than once results in // a compiler error. var attribute = assembly.GetCustomAttributes().OfType().SingleOrDefault(); if (attribute != null) { entryAssemblies.Add(assembly); } } // Note that we use LINQ Single to ensure we found one and only one assembly with the // EntryAssemblyAttribute. The EntryAssemblyAttribute should only be put on one assembly // per application. return entryAssemblies.Single(); } } } 

В качестве ответа на мой собственный вопрос (некоторые люди здесь очень трогательны по принятому тарифу) => Я не нашел лучшего способа, чем код, заданный в вопросе.

Это означает, что решение te не идеально, но оно работает так долго, как ваша базовая страница определена в интерфейсной сборке.

Алгоритм, предложенный в вопросе, действительно работал для меня, тогда как метод с использованием System.Web.HttpContext.Current.ApplicationInstance этого не сделал. Я думаю, что моя проблема в том, что приложение ASP.Net в старом стиле, для которого мне нужно решение, не имеет обработчика global.asax.

Это более короткое решение также работало для меня, и я думаю, что в целом будет работать при условии, что обработчик страницы определен в интерфейсной сборке:

  private static Assembly GetMyEntryAssembly() { if ((System.Web.HttpContext.Current == null) || (System.Web.HttpContext.Current.Handler == null)) return Assembly.GetEntryAssembly(); // Not a web application return System.Web.HttpContext.Current.Handler.GetType().BaseType.Assembly; } 

Мое приложение представляет собой приложение ASP.NET 4.x для веб-форм. Для этого типа приложения HttpContext.Current.Handler – это модуль кода, содержащий точку входа текущего обработчика запросов. Handler.GetType (). Assembly – это временная assembly ASP.Net, но Handler.GetType (). BaseType.Assembly – это истинная «assembly» моего приложения. Мне любопытно, если то же самое работает для разных других типов приложений ASP.Net.

Единственный способ, которым я смог заставить это работать последовательно для веб-приложений (по крайней мере, в .NET 4.5.1), – это выполнить Assembly.GetExecutingAssembly () в самом проекте веб-приложения.

Если вы попытаетесь создать проект утилит со статическими методами и выполните там вызов, вы получите информацию о сборке из этой сборки – для GetExecutingAssembly () и GetCallingAssembly ().

GetExecutingAssembly () – это статический метод, возвращающий экземпляр типа Assembly. Метод не существует в экземпляре самого classа Assembly.

Итак, что я сделал, был создан class, который принимает тип Assembly в конструкторе и создал экземпляр этого classа, передающий результаты Assembly.GetExecutingAssembly ().

  public class WebAssemblyInfo { Assembly assy; public WebAssemblyInfo(Assembly assy) { this.assy = assy; } public string Description { get { return GetWebAssemblyAttribute(a => a.Description); } } // I'm using someone else's idea below, but I can't remember who it was private string GetWebAssemblyAttribute(Func value) where T : Attribute { T attribute = null; attribute = (T)Attribute.GetCustomAttribute(this.assy, typeof(T)); if (attribute != null) return value.Invoke(attribute); else return string.Empty; } } } 

И использовать его

 string Description = new WebAssemblyInfo(Assembly.GetExecutingAssembly()).Description; 
  • В чем разница между ошибкой сегментации и переполнением стека?
  • Почему максимальная глубина рекурсии я могу достичь недетерминированной?
  • Вызов удаления по переменной, выделенной в стеке
  • что может привести к сбросу стоп-кадра (я использую «throw», а не «throw ex»)
  • c ++ Vector, что происходит, когда он расширяется / перераспределяется в стеке?
  • В чем разница между parent.frame () и parent.env () в R; как они отличаются при вызове по ссылке?
  • Как вернуться к последней запущенной деятельности при повторном запуске приложения после нажатия HOME?
  • Создание объекта в стеке / куче?
  • Как можно захватить трассировку стека в C?
  • Java / Android - Как распечатать полную трассировку стека?
  • Как реализовать очередь с использованием двух стеков?
  • Interesting Posts

    Сравните два варианта сценариев приложений Google

    Как определить, совместимо ли устройство Android в паре с Android-функцией

    Как отключить кеширование на стороне клиента и прокси в ASP.NET MVC?

    Может ли столбцы столбцов индекса PostgreSQL?

    Класс BaseAdapter не будет устанавливать адаптер внутри Asynctask – Android

    После последних обновлений Win8.1×64 моя система застряла при перезагрузке или отключении.

    Как восстановить удаленные разделы NTFS?

    Активная ссылка URL-адреса Android в TextView

    Почему проверка равенства не выполняется с массивами

    Дамп содержимого командной строки cmd в файл из пакетного файла

    Как изменить порядок привязки сетевых адаптеров в Windows 7?

    Минимизировать размер файлов Microsoft Word

    Как установить больше строк для прокрутки назад, в текстовом режиме?

    Список аргументов слишком длинный для команд rm, cp, mv

    Clonezilla диск для клонирования диска на двойной загрузке ubuntu karmic & XP setup – невозможно открыть '/boot/grub/device.map'

    Давайте будем гением компьютера.