asp.net mvc - как применить супертип уровня контроллера - PullRequest
5 голосов
/ 08 августа 2011

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

public class FooController : MyBaseController

Есть ли способ, которым я могу применить это, чтобы люди не могли создавать контроллеры, которые расширяют Controller напрямую?

Ответы [ 5 ]

6 голосов
/ 08 августа 2011

Вы всегда можете создать модульный тест, который (через отражение) извлекает все классы, производные от Controller и утверждает, что каждый класс также является подклассом MyBaseController. Это было бы по линии

[TestMethod]
public class All_Controllers_Derive_From_MyBaseController()
{
    // Act
    var controllerTypes = AppDomain.CurrentDomain
                                   .GetAssemblies()
                                   .SelectMany(asm => asm.GetTypes())
                                   .Where(t => t.IsSubclassOf(typeof(Controller))
                                   .ToList();

   // Verify
   foreach (var type in controllerTypes)
   {
        // Make sure the type isn't the actual controller type
        if (type is Controller)
            continue;

        Assert.IsTrue(type.IsSubclassOf(typeof(MyBaseController)), 
                           string.Format("{0} is not a subclass of the MyBaseController class", type.FullName));
   }
}

Теперь, если кто-то создаст контроллер, который не использует ваш базовый контроллер, ваши модульные тесты не пройдут и скажут вам, какие из них неверны.

Обратите внимание, что этот код был написан от руки, поэтому может потребоваться некоторая корректировка, но это основная идея.

3 голосов
/ 08 августа 2011

Однако я предпочитаю подход модульного тестирования выше , вот еще один с использованием фабрики пользовательских контроллеров.

public class MyControllerFactory<T> : DefaultControllerFactory where T : Controller
{
    #region Overrides of DefaultControllerFactory

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (!typeof(T).IsAssignableFrom(controllerType))
        {
            throw new NotSupportedException();
        }

        return base.GetControllerInstance(requestContext, controllerType);
    }

    #endregion
}

Вы можете настроить его в методе запуска приложения вашей Global.asax вот так:

ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory<MyBaseController>());

Это, конечно, вызывает исключение времени выполнения, если оно не является производным от MyBaseController, что может не подходить для вашего текущего сценария.

1 голос
/ 08 августа 2011

У вас есть два варианта, и оба связаны с написанием некоторого кода.

выбор # 1 Вы можете создать фильтр и попытаться отловить ошибку во время выполнения.Вам лучше иметь хороший хороший процесс проверки приемлемости для пользователей, чтобы охватить все страницы.

Вариант № 2 включает в себя написание задачи для MSBuild, которая проверяет, что каждый класс контроллера является производным от указанного вами класса.Просто загрузите сборку приложения (или сборки) и отправляйтесь в город!

Я предпочитаю вариант №2.Это не влияет на производительность приложения и дает вам лучший охват.Вы можете запустить его в конце сборки.

http://msdn.microsoft.com/en-us/library/gg416513(VS.98).aspx

http://msdn.microsoft.com/en-us/library/t9883dzc.aspx

0 голосов
/ 08 августа 2011

Вы можете изменить шаблон генерации кода по умолчанию, чтобы он всегда создавал новый контроллер, наследуемый от правильного класса.Недостатком является распространение обновленных шаблонов среди разработчиков.Более подробные инструкции см. В блоге Скотта Хансельмана.

http://www.hanselman.com/blog/ModifyingTheDefaultCodeGenerationscaffoldingTemplatesInASPNETMVC.aspx

0 голосов
/ 08 августа 2011

Я хочу подвергнуть сомнению ваши причины, но вот ответ: Один (слегка закулисный) метод, который вы могли бы использовать, - назвать базовый класс «Controller» и поместить его в то же пространство имен, что и ваши отдельные контроллеры.Пока люди специально не расширяют System.Web.Mvc.Controller, они получат ваш класс Controller.Никто, возможно, не мудрее.

...