代码之家  ›  专栏  ›  技术社区  ›  moribvndvs

为ASP.NET MVC 2.0应用程序注册区域时提供或筛选程序集

  •  6
  • moribvndvs  · 技术社区  · 15 年前

    我有一个大型应用程序,它目前是webforms和mvc 2.0的混合体。启动我的应用程序是很可怕的,罪魁祸首主要是因为 AreaRegistration.RegisterAllAreas 打电话。更具体地说,它使用 System.Web. Compilation.BuildManager.GetReferencedAssemblies 枚举应用程序直接引用的程序集中的所有类型,并测试它们是否派生自 AreaRegistration .

    不幸的是,我有很多第三方程序集,它们碰巧非常广泛,所以这个初始加载可能非常糟糕。如果我能告诉它要查找哪些程序集,我会得到更好的结果 AreaRegistrations ,甚至暂时手动注册区域。

    我可以收集所有的内部信息 区域登记 创建并调用注册,但我只是好奇其他人是否已经解决了这个问题。

    2 回复  |  直到 15 年前
        1
  •  14
  •   moribvndvs    15 年前

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

    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
  •  2
  •   anthonyv    15 年前

    我不能百分之百确定这是否有助于在这种特定的情况下,但你能把你所有的第三方dll合并成一个dll(因此删除所有单独文件的处理)。这就是我们在构建时使用ilmerge所做的。很有魅力。它仍然需要查看dll的元数据(现在会更大一些),但它不需要做那么多io。