9

我正在阅读 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

为什么这样做,它实现了什么?似乎没有任何用处。

4

3 回答 3

6

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

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

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

于 2012-04-12T21:57:17.773 回答
2

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

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

在相关测试中,他们在ControllerBase调用.IControllerExecute

于 2012-04-12T21:51:00.397 回答
1

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

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

于 2012-04-12T21:53:56.250 回答