【问题标题】:What is the point of this code?这段代码有什么意义?
【发布时间】:2012-04-12 21:11:07
【问题描述】:

我正在阅读 ASP.NET MVC3 的源代码,在ControllerBase 的代码中发现了以下内容:

public interface IController
{
    void Excecute(RequestContext requestContext);
}


public abstract class ControllerBase : IController
{

    protected virtual void Execute(RequestContext requestContext)
    {
        if (requestContext == null)
        {
            throw new ArgumentNullException("requestContext");
        }
        if (requestContext.HttpContext == null)
        {
            throw new ArgumentException(MvcResources.ControllerBase_CannotExecuteWithNullHttpContext, "requestContext");
        }

        VerifyExecuteCalledOnce();
        Initialize(requestContext);

        using (ScopeStorage.CreateTransientScope())
        {
            ExecuteCore();
        }
    }

    void IController.Execute(RequestContext requestContext)
    {
        Execute(requestContext);
    }
}

ControllerBase 提供了Execute 的实现,但它有一些东西可以为..IController.Execute 提供定义?

为什么要这样做,它实现了什么?好像没什么用。

【问题讨论】:

  • 如果你覆盖了虚拟的Execute,显式的IController.Execute 还会执行基础实现吗?
  • @Joe 不。如果存在,它将执行覆盖的虚拟执行。
  • 因此,获得该方法protected 而不是public 可能只是一个技巧。
  • @Joe 可能是。这就是 vhallac 的建议,强制执行职责分离。

标签: asp.net-mvc-3 interface implementation


【解决方案1】:

此代码使您可以覆盖 Execute 方法。

请记住,通常实现的接口方法是公共的(而不是虚拟或抽象的),因此您不能在派生类中重写它,并且默认情况下无法通过 IController 接口访问创建新的 Execute 方法(没有这个接口到受保护的虚拟技术)。通过创建受保护的虚拟方法(从显式实现的接口方法调用),派生类可以覆盖 Execute 方法,而不会破坏接口实现。

我在这里找到了一篇很棒的文章: C# Overriding Interface Methods in Subclasses

【讨论】:

  • 所以本质上,如果我想通过接口公开一些我想在子类中更改的功能,我可以使用这种模式。
  • 相比public virtual Execute(RequestContext requestContext),您为什么更喜欢这种设计模式?
  • @Scott 使用 public virtual 将允许从此类外部访问它,而无需引用 IController 接口。会公开的。使用 protected 使您的方法保持在 ControllerBase 类及其后代的内部,除非您有对 IController 接口的显式引用。所以它得到了更好的保护,只有在非常有意访问时才使用。
【解决方案2】:

根据MSDN Documentation,显式接口成员实现的一个目的是:“因为显式接口成员实现不能通过类或结构实例访问,它们允许将接口实现从类或结构的公共接口中排除。当一个类或结构实现一个对该类或结构的使用者不感兴趣的内部接口时,这尤其有用。"

如果我对上面的解释是正确的,那么ControllerBase 类型的变量不能用于调用Execute,因为它是受保护的。变量的类型必须是IController。我不确定这是否是构造的意图,但感觉这就是原因。

在相关测试中,他们在调用Execute之前将ControllerBase变量显式转换为IController

【讨论】:

  • 是的。也许这只是一种从“外部”掩盖 Execute 调用的奇特方式。
  • @Scott 我的猜测是这用于强制职责分离。如果您持有ControllerBase 引用,则不打算执行它。如果您持有IController,则只能执行它。
【解决方案3】:

乍一看,这种设计模式似乎毫无用处。然而,它确实为ControllerBase 类提供了在以后对其IController 接口的实现进行非破坏性更改的机会。更改将保证运行,因为它不依赖于调用base.Execute() 的继承类。也许这可以在未来用于管理上下文或安全性?

也许开发人员只是喜欢将接口与可覆盖的实现保持逻辑分离。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多