我正在阅读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
?
为什么要这样做,它实现了什么?似乎它没有用处。
答案 0 :(得分:6)
此代码使您可以覆盖Execute方法。
请记住,正常实现的接口方法是公共的(而不是虚拟或抽象),因此您无法在派生类中覆盖它,并且无法通过IController
接口创建新的Execute方法。默认(没有此受保护虚拟技术的接口)。通过创建受保护的虚方法(您从显式实现的接口方法调用),允许派生类覆盖Execute方法,而不会破坏接口实现。
我在这里发现了一篇很好的文章: C# Overriding Interface Methods in Subclasses
答案 1 :(得分:2)
根据MSDN Documentation,显式接口成员实现的一个目的是:“因为显式接口成员实现不能通过类或结构实例访问,所以它们允许从类的公共接口中排除接口实现或当一个类或结构实现一个对该类或结构的使用者不感兴趣的内部接口时,这个特别有用。“
如果我对上述内容的解释是正确的,则ControllerBase
类型的变量不能用于调用Execute
,因为它受到保护。变量的类型必须是IController
。我不确定这是否是构造的意图,但感觉这就是原因。
在相关测试中,他们在致电ControllerBase
之前明确将IController
变量投放到Execute
。
答案 2 :(得分:1)
ControllerBase
类提供了以后对IController
接口的实现进行非破坏性更改的机会。这些更改将保证运行,因为它不依赖于调用base.Execute()
的继承类。也许这可以用来管理未来的环境或安全性?
也许开发人员只是喜欢将界面与可覆盖的实现保持逻辑分离。