asp.net mvc - 如何强制执行控制器层超类型

Dav*_*vid 5 asp.net-mvc design-patterns controller

我想Controller在我的项目中使用一个扩展为控制器默认基类型的类,而不是使用Controller它自己.所以,我会这样做:

public class FooController : MyBaseController
Run Code Online (Sandbox Code Playgroud)

有没有办法可以强制执行此操作,以便人们无法创建Controller直接扩展的控制器?

Kal*_*exx 6

您始终可以创建一个单元测试(通过反射)检索从中派生的所有类,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));
   }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果有人创建了一个不使用基本控制器的控制器,则单元测试将失败并告诉您哪些控制器不正确.

请注意,此代码是自由编写的,因此可能需要进行一些调整,但这是基本的想法.


gus*_*.dr 3

不过,我更喜欢上面的单元测试方法,这是使用自定义控制器工厂的另一种方法。

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
}
Run Code Online (Sandbox Code Playgroud)

您可以在 Global.asax 的应用程序启动方法中进行设置,如下所示:

ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory<MyBaseController>());
Run Code Online (Sandbox Code Playgroud)

这当然会在不派生时导致运行时异常MyBaseController,这可能不适合您当前的场景。