是否应将来自不同控制器的相同方法移动到CommonController?

时间:2018-03-05 10:04:05

标签: c# asp.net-mvc

我有两个控制器,它们的方法相同:

public class Controller1 : Controller
{
    private readonly ITestBL bl;

    public Controller1(ITestBL bl)
    {
        this.bl= bl;
    }

    [HttpGet]
    public ActionResult Method1(string data)
    {
        using (bl)
        {
            var res = ...

            return Json(res, JsonRequestBehavior.AllowGet);
        }
    }

    [HttpGet]
    public ActionResult Method2(string data, int data2)
    {
        using (bl)
        {
            var res = ...

            return Json(res, JsonRequestBehavior.AllowGet);
        }
    }

    // other methods
}

第二个控制器也有这两种方法。

我应该创建一些通用控制器来保留这些方法吗?所以,它看起来像这样:

public abstract class CommonController: Controller
{
    private readonly ITestBL bl;

    protected Controller1(ITestBL bl)
    {
        this.bl= bl;
    }

    [HttpGet]
    public ActionResult Method1(string data)
    {
        using (bl)
        {
            var res = ...

            return Json(res, JsonRequestBehavior.AllowGet);
        }
    }

    [HttpGet]
    public ActionResult Method2(string data, int data2)
    {
        using (bl)
        {
            var res = ...

            return Json(res, JsonRequestBehavior.AllowGet);
        }
    }
}

我的Controller1Controller2将是:

public class Controller1 : CommonController
{
        private readonly ITestBL bl;

        public Controller1(ITestBL bl)
            :base(bl)
        {
        }

        // methods
}

这是正确的方法吗?我是否想念任何事情或有更好的方法吗?

2 个答案:

答案 0 :(得分:1)

  

是否应将来自不同控制器的相同方法移至CommonController?

是的,您不应使用继承。我敢肯定有很多人可能会不同意,但是您的示例是非常通用的,并且上下文很差。没有充分的理由说明所有控制器都需要相同的代码(是否继承)。您的问题上下文没有理由在Has A vs Is A 的OOP领域中发生(以下摘录)。

  • 房屋建筑物(继承);
  • 一所房子有一间房间(组成);

您似乎在做什么都不是

现在,如果您的界面是IVehicleEngine,而您的控制器是FerarriVehicleControllerFordVehicleController,那么在上下文中就可以了。在这种情况下,每个控制器都应该使用继承,这很有意义。

以我自己的拙见,从多个方面继承您自己的控制器可能非常困难。首先,它不直观。那将成为tribal knowledge,因为它取代了大多数程序员遵循的常规约定(该约定是从基本MVC控制器派生的)。其次,我已经看到它成为每个人都决定向(God Object)添加代码的地方,即使它可能不适用于某些控制器。第三,很难重用对派生类型有意义但对基本类型(/search?searchFor=不适用)的url。由于MVC暴露在网络中(安全性等),因此还有许多其他一些特定于MVC的注意事项。

根据实现方式,您可能还难以确定在什么情况下使用哪个URL。

/Controller1/Method1/Data/1/Controller2/Method1/Data/1相同但与/Controller3/Method1/Data/1不同吗?如果它们全部相同某些相同但有些不同,则很可能是该体系结构有问题。

答案 1 :(得分:0)

从基本控制器继承没有问题。由于它遵循DRY原理。我会选择:

public abstract class CommonController: Controller
{
    protected readonly ITestBL bl;

    protected Controller1(ITestBL bl)
    {
        this.bl= bl;
    }

    [HttpGet]
    public virtual ActionResult Method1(string data)
    {
            var res = ...

            return Json(res, JsonRequestBehavior.AllowGet);
    }

    [HttpGet]
    public virtual ActionResult Method2(string data, int data2)
    {
            var res = ...

            return Json(res, JsonRequestBehavior.AllowGet);
    }
}

主要区别在于。

  1. 我删除了“使用”。就像其他人所说的那样,最好让您的DI框架决定何时处置注入的类。
  2. 将操作结果虚拟化。继承的控制器现在可能具有相同的要求,但不能保证它们将来会保持这种状态。因此,将它们声明为虚拟允许将来在范围/要求方面进行更改,因为它们可以被覆盖。
  3. 我将注入的类设置为“保护”而不是“私有”,因为两个继承控制器中的其他方法可能也需要它。