9

現在、WebFormsとMVC2.0のハイブリッドとして存在する大規模なアプリケーションがあります。私のアプリケーションの起動は恐ろしいものであり、原因は主にAreaRegistration.RegisterAllAreas呼び出しによるものです。具体的には、を使用してSystem.Web. Compilation.BuildManager.GetReferencedAssemblies、アプリケーションによって直接参照されるアセンブリ内のすべてのタイプを列挙し、それらがから派生しているかどうかをテストしますAreaRegistration

残念ながら、私は非常に広範囲にわたるサードパーティのアセンブリをいくつか持っているので、この初期ロードはかなり悪い可能性があります。どのアセンブリを探すAreaRegistrationsか、または当面は手動で領域を登録するかを指示できれば、はるかに良い結果が得られます。

のすべての内部を集めてAreaRegistration登録を作成して呼び出すことはできますが、他の人がこの問題を抱えて回避したかどうかだけが気になります。

4

2 に答える 2

16

エリアを登録するためのアセンブリを分離するために、次のユーティリティをまとめました。エリア登録の内部をハックアウトする必要がありましたが、それほど複雑ではないようで、これは私にとってかなりうまく機能しています。

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

これにより、起動時間が大幅に改善されましたが、エリアに立ち寄ってアプリケーションに自動的に登録させることができなくなりました。ただし、この場合、それは私の懸念事項ではありません。

于 2010-04-26T16:37:24.200 に答える
2

これがこの特定のケースで役立つかどうかは100%わかりませんが、すべてのサードパーティのdllを1つのdllに結合できます(したがって、すべての個々のファイルの処理を削除できます)。これは、ビルド時にILMergeを使用して行ったことです。チャームのように機能します。dllのメタデータ(これで少し大きくなります)を確認する必要がありますが、それほど多くのIOを実行する必要はありません。

于 2010-03-23T02:01:06.703 に答える