Предоставление или фильтрация сборок при регистрации областей для приложения ASP.NET MVC 2.0 - PullRequest
7 голосов
/ 23 марта 2010

У меня есть большое приложение, которое в настоящее время существует как гибрид WebForms и MVC 2.0. Запуск моего приложения ужасен, и виновник в основном из-за вызова AreaRegistration.RegisterAllAreas. В частности, он использует System.Web. Compilation.BuildManager.GetReferencedAssemblies для перечисления всех типов в сборках, на которые непосредственно ссылается приложение, и проверки их, чтобы определить, являются ли они производными от AreaRegistration.

К сожалению, у меня есть несколько сторонних сборок, которые оказываются достаточно обширными, поэтому эта начальная загрузка может быть довольно плохой. Я получил бы намного лучшие результаты, если бы мог сказать, какие сборки искать AreaRegistrations, или даже зарегистрировать области вручную.

Я могу собрать все внутренние элементы AreaRegistration, чтобы создать и вызвать регистрацию, но мне просто любопытно, если бы другие имели и работали над этой проблемой.

Ответы [ 2 ]

14 голосов
/ 26 апреля 2010

Я собрал следующую утилиту, чтобы изолировать сборки для регистрации областей. Мне пришлось взломать внутреннюю часть регистрации области, но они не кажутся очень сложными, и это работает довольно хорошо для меня:

using System;
using System.Linq;
using System.Reflection;
using System.Web.Mvc;
using System.Web.Routing;

namespace MyCompany.Web.Mvc
{
    /// <summary>
    /// Provides helpful utilities for performing area registration, where <see cref="AreaRegistration.RegisterAllAreas()"/> may not suffice.
    /// </summary>
    public static class AreaRegistrationUtil
    {
        /// <summary>
        /// Registers all areas found in the assembly containing the given type.
        /// </summary>
        /// <typeparam name="T">A type that derives from <see cref="AreaRegistration"/> and has a default constructor.</typeparam>
        public static void RegisterAreasForAssemblyOf<T>()
            where T : AreaRegistration, new()
        {
            RegisterAreasForAssemblyOf<T>(null);
        }

        /// <summary>
        /// Registers all areas found in the assembly containing the given type.
        /// </summary>
        /// <typeparam name="T">A type that derives from <see cref="AreaRegistration"/> and has a default constructor.</typeparam>
        /// <param name="state">An object containing state that will be passed to the area registration.</param>
        public static void RegisterAreasForAssemblyOf<T>(object state)
            where T : AreaRegistration, new()
        {
            RegisterAreasForAssemblies(state, typeof (T).Assembly);
        }

        /// <summary>
        /// Registers all areas found in the given assemblies.
        /// </summary>
        /// <param name="assemblies"><see cref="Assembly"/> objects containing the prospective area registrations.</param>
        public static void RegisterAreasForAssemblies(params Assembly[] assemblies)
        {
            RegisterAreasForAssemblies(null, assemblies);
        }

        /// <summary>
        /// Registers all areas found in the given assemblies.
        /// </summary>
        /// <param name="state">An object containing state that will be passed to the area registration.</param>
        /// <param name="assemblies"><see cref="Assembly"/> objects containing the prospective area registrations.</param>
        public static void RegisterAreasForAssemblies(object state, params Assembly[] assemblies)
        {
            foreach (Type type in
                from assembly in assemblies
                from type in assembly.GetTypes()
                where IsAreaRegistrationType(type)
                select type)
            {
                RegisterArea((AreaRegistration) Activator.CreateInstance(type), state);
            }
        }

        /// <summary>
        /// Performs area registration using the specified type.
        /// </summary>
        /// <typeparam name="T">A type that derives from <see cref="AreaRegistration"/> and has a default constructor.</typeparam>
        public static void RegisterArea<T>()
            where T : AreaRegistration, new()
        {
            RegisterArea<T>(null);
        }

        /// <summary>
        /// Performs area registration using the specified type.
        /// </summary>
        /// <typeparam name="T">A type that derives from <see cref="AreaRegistration"/> and has a default constructor.</typeparam>
        /// <param name="state">An object containing state that will be passed to the area registration.</param>
        public static void RegisterArea<T>(object state)
            where T : AreaRegistration, new()
        {
            var registration = Activator.CreateInstance<T>();
            RegisterArea(registration, state);
        }

        private static void RegisterArea(AreaRegistration registration, object state)
        {
            var context = new AreaRegistrationContext(registration.AreaName, RouteTable.Routes, state);
            string ns = registration.GetType().Namespace;

            if (ns != null) context.Namespaces.Add(string.Format("{0}.*", ns));

            registration.RegisterArea(context);
        }

        /// <summary>
        /// Returns whether or not the specified type is assignable to <see cref="AreaRegistration"/>.
        /// </summary>
        /// <param name="type">A <see cref="Type"/>.</param>
        /// <returns>True if the specified type is assignable to <see cref="AreaRegistration"/>; otherwise, false.</returns>
        private static bool IsAreaRegistrationType(Type type)
        {
            return (typeof (AreaRegistration).IsAssignableFrom(type) && (type.GetConstructor(Type.EmptyTypes) != null));
        }
    }
}

Самый простой способ использовать это, для меня, это

AreaRegistrationUtil.RegisterAreasForAssemblyOf<SomeTypeInTargetAssembly>();

Это значительно улучшило время запуска за счет невозможности попасть в область и автоматически зарегистрировать приложение. Однако в данном случае это не мое дело.

2 голосов
/ 23 марта 2010

Я не уверен на 100%, поможет ли это в данном конкретном случае, но не могли бы вы объединить все свои сторонние dll в один dll (следовательно, исключив обработку всех отдельных файлов). Это то, что мы сделали, используя ILMerge во время сборки. Работает как шарм. Ему все еще нужно будет посмотреть метаданные для библиотеки DLL (которая теперь будет немного больше), но для этого не нужно будет делать столько операций ввода-вывода.

...