在为 ASP.NET MVC 2.0 应用程序注册区域时提供或过滤程序集

2023-11-24

我有一个大型应用程序,目前作为 WebForms 和 MVC 2.0 的混合体存在。我的应用程序的启动非常糟糕,罪魁祸首主要是因为AreaRegistration.RegisterAllAreas称呼。更具体地说,它正在使用System.Web. Compilation.BuildManager.GetReferencedAssemblies枚举应用程序直接引用的程序集中的所有类型并测试它们以查看它们是否派生自AreaRegistration.

不幸的是,我有许多第三方程序集,它们的范围非常广泛,因此初始加载可能非常糟糕。如果我能告诉它要查找哪些程序集,我会得到更好的结果AreaRegistrations,或者暂时手动注册区域。

我可以收集所有的内部结构AreaRegistration创建并调用注册,但我只是好奇其他人是否已经遇到并解决了这个问题。


我将以下实用程序放在一起来隔离用于注册区域的程序集。我必须破解区域注册的内部结构,但它们看起来并不太复杂,而且这对我来说运行得相当好:

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

这显着缩短了启动时间,但代价是无法进入某个区域并让应用程序自动注册它。然而,在本例中这不是我关心的问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在为 ASP.NET MVC 2.0 应用程序注册区域时提供或过滤程序集 的相关文章

随机推荐