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