C# 是否应将来自不同控制器的相同方法移动到公共控制器?

C# 是否应将来自不同控制器的相同方法移动到公共控制器?,c#,asp.net-mvc,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)

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

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);
        }
    }
}
我的
Controller1
Controller2
将是:

public class Controller1 : CommonController
{
        private readonly ITestBL bl;

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

        // methods
}

这样做正确吗?我是否错过了什么,或者有更好的方法吗?

从基本控制器继承没有错。因为它坚持干燥原则。我同意:

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);
    }
}
主要区别在于

  • 我删除了“使用”。正如其他人所说,最好让您的DI框架决定何时处置注入的类
  • 使动作结果虚拟化。继承控制器现在可能有相同的要求,但不能保证它们将来会保持这种状态。因此,将它们声明为虚拟允许将来对范围/需求进行更改,因为它们可以被覆盖
  • 我将注入的类设置为“protected”而不是“private”,因为两个继承控制器中的其他方法可能也需要它
  • 是否应将来自不同控制器的相同方法移动到公共控制器

    是的,您不应该使用继承。我相信有很多人可能不同意,但是您的示例非常通用,并且提供了非常糟糕的上下文。没有理由所有控制器都需要相同的代码(继承或不继承)。您的问题上下文没有理由在的OOP领域出现这种情况(下面摘录)

    • 房子是建筑物(遗产)
    • 房子有一个房间(构成)
    看起来你正在做的不是这些

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

    依我个人的拙见,从你自己的控制者那里继承可能在多个方面相当困难。首先,它不是直观的;这是因为它取代了大多数程序员遵守的常规(即从基本MVC控制器派生出来的常规)。其次,我看到它成为了一个每个人都决定向()添加代码的地方,尽管它可能不适用于某些控制器。第三,这使得重用对派生类型有意义但对基类型没有意义的url变得困难(
    /search?searchFor=
    )。由于MVC暴露于web(安全性等),因此还有许多其他的考虑事项非常特定于MVC

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


    /Controller1/Method1/Data/1
    是否与
    /Controller2/Method1/Data/1
    相同,但与
    /Controller3/Method1/Data/1
    不同?如果它们都相同,或者有些相同,有些不同,那么架构很可能有问题。

    是的,所有常见的东西都应该放在一个公共基类中,如果可能的话,这样可以避免代码重复。也就是说,您使用的
    语句看起来不太好。。。至少可以这么说,它们似乎是一个非常糟糕的主意。@在这两者之间,应该是这样的:“var res;using(bl){res=…;}return res;”?不。首先,不要处理你不拥有的东西
    bl
    是通过构造函数注入的,让谁来决定何时处置它。其次,
    bl
    在退出
    Method1
    Method2
    之前被释放(这就是
    使用
    语句所保证的)。对任何一个的第一次调用都会起作用,任何后续调用
    bl
    都将被处理,这对调用的结果来说都不是好兆头,但正如我所说的,您没有必要从一开始就处理它。@interween:完全同意
    使用
    的问题。然而,由于MVC不断地重新设计控制器来处理单个请求,OP可能不会遇到任何问题,只要他只在操作结束时处理对象。当然,这仍然不是好的做法。