【问题标题】:Override a protected internal virtual method in c#在 C# 中覆盖受保护的内部虚拟方法
【发布时间】:2010-09-04 21:27:50
【问题描述】:

我正在尝试像这样构建一个类...

    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;
        }

    }

该方法正在尝试覆盖具有以下签名的内部虚拟方法(来自 .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

网络上的每个人似乎都能很好地做到这一点,有什么明显的我遗漏了吗?

【问题讨论】:

  • GetControllerInstance 的签名中删除internal?这行得通吗?
  • @Jason,该方法是在 ASP.NET MVC 程序集中定义的,不能修改
  • 这里是另一个扳手......如果我将它从我的原始程序集中删除,程序集就会建立!这真的难倒我。
  • 你确定你在某个地方没有另一个 DefaultControllerFactory 类吗?或另一个 IController 接口?我没有看到任何其他解释
  • @wcpro:你看到我的更新了吗?我觉得我已经解决了这个问题,应该可以消除你的困惑。

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


【解决方案1】:

新的(可能的)答案

如果我在我自己的库中定义了与“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 的方法覆盖它,这会删除对所有非派生类型的访问,即使在与基类型相同的程序集中也是如此。

这与尝试用private 覆盖public 成员并没有太大区别。你不能那样做;您必须声明派生成员 new 而不是 override(这几乎是一个非常糟糕的主意)。

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

更新:实际上,正如 Thomas 在评论中指出的那样,这完全取决于您的派生类型是否与基类型在同一个程序集中。如果不是,那么声明派生成员protected internal 将毫无意义。如果您在不同的程序集中,那么我不确定为什么声明成员 protected 会导致错误,因为这正是您应该做的。

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

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

【讨论】:

  • 不,protected internal 方法应该被覆盖为protected。如果您尝试将它们覆盖为protected internal,则会出现编译错误。见this answerprotected internal 将允许对程序集中的所有类访问此方法,这会错误地扩大其可访问性
  • 嗯,这是我最初的想法,但是如果您使用任何 MVC IoC 框架在谷歌上搜索这个特定的场景,他们 100% 能够按照描述完成此操作。当我将它移动到不同的程序集并构建它时,它也可以正常工作。
  • @Thomas, @wcpro:查看我的更新。我认为它解决了你们俩所说的问题。
  • @Thomas Levesque:我错过了什么吗?看来你不信。
  • 这是一个我试图覆盖的 .NET 程序集。我无法更改该程序集的签名。
【解决方案2】:

我刚刚遇到了这个问题;如果选择的解决方案不是您真正的问题,那么 RequestContext 类型是从 System.Web.Routing 程序集转发到 System.Web 程序集的。解决方案是同时引用 System.Web 和 System.Web.Routing。

【讨论】:

    猜你喜欢
    • 2019-01-25
    • 2013-07-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-01
    • 1970-01-01
    • 2014-04-08
    • 2011-08-04
    • 2016-12-26
    相关资源
    最近更新 更多