在c#中覆盖受保护的内部虚拟方法

时间:2010-09-04 21:27:50

标签: c# .net asp.net inversion-of-control

我正在尝试建立一个像这样的课程......

    public class IoCControllerFactory : DefaultControllerFactory
    {           
        protected override IController GetControllerInstance(RequestContext request_context, Type controller_type)
        {
            // Attempt to resolve controller type.
            IController resolvedController = null;
            if (controller_type != null)
            {

                if (!typeof(IController).IsAssignableFrom(controller_type))
                {
                    throw new ArgumentException(string.Format("Type requested is not a controller: {0}", controller_type.Name), "controller_type");
                }

                resolvedController = _container.Resolve(controller_type) as IController;
            }

            // Throw page not found if controller does not exist.
            if (resolvedController == null)
            {
                throw new HttpException((int)HttpStatusCode.NotFound, "The requested page was not found.");
            }

            return resolvedController;
        }

    }

该方法试图覆盖具有followign签名的内部虚拟方法(来自.net程序集...我无法修改此内容)

protected internal virtual IController GetControllerInstance(
    RequestContext requestContext,
    Type controllerType
)

当我尝试编译时,我得到以下内容......

'XXX.Web.Mvc.IoCControllerFactory.GetControllerInstance(System.Web.Routing.RequestContext, System.Type)': no suitable method found to override

网上的每个人似乎都能做得很好,有什么明显的东西我不知道吗?

2 个答案:

答案 0 :(得分:2)

新(可能)答案

如果我已经定义了一个与我自己的库中的“System.Web.Mvc.dll”程序集中的名称相同的类型,我可以复制此问题。 这可能是您的问题吗?请参阅以下代码:

using System;
using System.Web.Mvc;
using System.Web.Routing;

namespace SystemWebMvcTest
{
    // See here: I've declared a type with the same name as a type
    // from the System.Web.Mvc namespace in System.Web.Mvc.dll.
    public interface IController
    {
    }

    public class IoCControllerFactory : DefaultControllerFactory
    {
        // Now this method signature, since it does not include the fullly
        // qualified name of its return type, is actually defined to return
        // an instance of the IController interface defined in THIS assembly,
        // rather than the System.Web.Mcv.IController interface.
        protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            return null;
        }
    }
}

如果您与任何相关类型存在命名冲突,则会出现同样的错误:DefaultControllerFactoryIControllerRequestContextType


旧答案

原始方法是protected internal,这意味着可以通过同一个程序集中的任何类型访问它,也可以访问任何派生类型;但是您尝试使用protected方法覆盖它,这会删除对所有非派生类型的访问权限,即使在与基本类型相同的程序集中也是如此。

这与尝试使用public覆盖private成员完全不同。你做不到;你必须声明派生成员new而不是override(这几乎是所有时间都是一个非常糟糕的主意)。

标记您的IoCControllerFactory.GetControllerInstance方法protected internal,您应该做得很好。

UPDATE :实际上,正如托马斯在评论中指出的那样,这完全取决于派生类型是否与基本类型在同一个程序集中。如果,则声明派生成员protected internal没有任何意义。如果你在一个不同的程序集中,那么我不确定为什么声明成员protected导致错误,因为这正是你应该做的。

更新2 听起来就像你发布的代码一样,你的基类和派生类型都在同一个程序集中。这就是必须将IoCControllerFactory.GetControllerInstance方法标记为protected internal以匹配其基本类型的可访问性的原因。如果你在一个单独的程序集中,internal会出错,因为它会打开一组全新类型(这个新程序集中的类型)的可访问性。如果您已经在线看到代码示例,其中一个程序集中的类型从另一个程序集中的基类型继承了protected internal成员,这就解释了为什么派生成员只是protected - 保持可访问性相同。

更新3 :没关系!显然,基本类型是在.NET程序集中,这与派生类型所处的任何程序集明显不同。基于此,您的方法签名实际上应该按原样编译,据我所知。我想到的一个问题是,所有这些名称 - DefaultControllerFactoryIControllerRequestContext等 - 是否也不在您的程序集中。如果您有命名冲突,这可能是一种可能的解释。否则,我无法理解你得到的编译器错误。

答案 1 :(得分:1)

我刚遇到这个问题;如果所选择的解决方案确实不是您的问题,那么RequestContext类型是从System.Web.Routing程序集中提供到System.Web中的。解决方案是引用System.Web和System.Web.Routing。