在 C# 中重写受保护的内部虚拟方法

发布于 2024-09-17 01:27:14 字数 1519 浏览 0 评论 0原文

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

    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

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

I am trying to build a class like so...

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

    }

The method is trying to override an internal virtual method that has the followign signature (from .net assembly... i cant modify this)

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

When i try to compile i get the following...

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

Everybody on the web seems to be able to do this just fine, is there something obvious that I am missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

樱桃奶球 2024-09-24 01:27:14

新的(可能的)答案

如果我定义了一个与我自己的库中的“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;
        }
    }
}

如果您与任何相关类型发生命名冲突,也会出现相同的错误:DefaultControllerFactoryIController< /code>、RequestContextType


旧答案

原始方法是受保护的内部方法,这意味着同一程序集中的任何类型以及任何派生类型都可以访问它;但您尝试使用受保护的方法覆盖它,该方法将删除对所有非派生类型的访问,即使在与基类型相同的程序集中也是如此。

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

标记你的 IoCControllerFactory.GetControllerInstance 方法 protected inside ,你应该没问题。

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

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

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

New (Possible) Answer

I am able to duplicate this issue if I've defined a type with the same name as one from the "System.Web.Mvc.dll" assembly in my own library. Could this be your problem? See the code below:

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

The same error should occur if you have a naming conflict with any of the relevant types: DefaultControllerFactory, IController, RequestContext, or Type.


Old Answer

The original method is protected internal, which means that it can be accessed by any type within the same assembly as well as any derived type; but you are trying to override it with a method that is protected, which removes access to all non-derived types, even in the same assembly as the base type.

This isn't really so different from trying to override a public member with a private one. You can't do that; you'd have to declare the derived member new instead of override (which is a pretty bad idea, almost all the time).

Mark your IoCControllerFactory.GetControllerInstance method protected internal and you should be good.

UPDATE: Actually, as Thomas pointed out in a comment, this totally depends on whether your derived type is in the same assembly as the base type or not. If not, then declaring the derived member protected internal would make no sense. If you're in a different assembly, then I'm not sure why declaring the member protected is causing an error as this is exactly what you're supposed to do.

UPDATE 2: It sounds like in the code you've posted, your base and derived types are in the same assembly. This is why the IoCControllerFactory.GetControllerInstance method must be marked protected internal, to match the accessibility of its base type. If you were in a separate assembly, internal would be wrong, as it would open up the accessibility to a whole new set of types (those within this new assembly). If you've seen code examples online where a type in one assembly inherited a protected internal member from a base type in another, this explains why the derived member was only protected -- to keep accessibility the same.

UPDATE 3: Never mind! Apparently the base type is in a .NET assembly, which is clearly different from whatever assembly your derived type is in. Based on this, your method signature should actually compile as-is, as far as I can tell. One question in my mind is whether all of these names -- DefaultControllerFactory, IController, RequestContext, etc. -- are not also present in your assembly. If you have a naming conflict, this could be one possible explanation. Otherwise, I fail to understand the compiler error you're getting.

街角卖回忆 2024-09-24 01:27:14

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

I've just came across this problem; If the chosen solution wasn't really your problem, then is that the RequestContext type is forwared from the System.Web.Routing assembly into the System.Web one. The solution is to both reference System.Web and System.Web.Routing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文