如何扩展同名方法并调用?

时间:2011-12-01 03:01:41

标签: c# asp.net-mvc extension-methods override

我喜欢在类中重写一个方法,所以我使用相同的名称和参数扩展该方法,但它永远不会被调用。

http://msdn.microsoft.com/en-us/library/bb383977.aspx

....永远不会调用与接口或类方法具有相同名称和签名的扩展方法。 ....

好的,我必须接受这个。

我的问题是: 对于未密封的类(甚至我有源代码),如果我想重写类的方法 OUTSide (在不同的项目中但是相同的解决方案),怎么做?

[编辑]

这是建议的方式,使用虚拟/覆盖,运行时没有错误,编译时没有错误,只是永远不会被调用:(,请看看

在项目A中:

public class CachePlan : ICachePlan
{
    public virtual CacheSettings GetPlan(ControllerContext filterContext)
    {
        return null;
    }
}

在项目B中:

public class CachePlanExtension: CachePlan
{
    public override CacheSettings GetPlan(ControllerContext filterContext)
    {
        CacheSettings ca = new CacheSettings();
        ca.IsCachingEnabled = true;
        ca.Duration = 100;
        return ca;
    }
}

但永远不会被调用,CashPlan.GetPlan仍然返回null。 Anyidea吗

6 个答案:

答案 0 :(得分:3)

您无法“进入”现有类并更改其方法的含义。那将是一个重大的安全漏洞。

答案 1 :(得分:1)

简单地说; “不可能”。正如页面上所解释的那样......

  

您可以使用扩展方法扩展类或接口,但不能   覆盖他们。具有相同名称和签名的扩展方法   作为接口或类方法将永远不会被调用。在编译时,   扩展方法的优先级始终低于实例方法   在类型本身中定义。换句话说,如果类型有方法   命名为Process(int i),你有一个扩展方法   签名,编译器将始终绑定到实例方法。什么时候   编译器遇到方法调用,它首先查找一个   匹配类型的实例方法。如果找不到匹配,则会   搜索为该类型定义的任何扩展方法,和   绑定到它找到的第一个扩展方法。

答案 2 :(得分:1)

如果你有源代码,为什么不简单地从原始类中删除方法的实现,并在单独的项目中提供扩展方法

答案 3 :(得分:1)

扩展方法只是合成糖,它被编译成静态方法调用。所以你可以编写一个静态方法来完成同样的事情,你根本无法按照你喜欢的方式调用它。如果方法是虚拟的,则可以在派生类中覆盖它。只需确保始终实例化您自己的类型。您也可以使用new关键字,但是不会使用简单的强制转换和代码。最好是为自己创建一个简单的包装类。该类将有一个有问题的类的实例,并找出正确的调用。这在创建特殊集合时非常常见,因为很多.NET集合类型都不适合继承。但最糟糕的是,你可以使用Moles

修改

创建自己的继承自ActionFilterAttribute的类,并使用它创建自己的自定义过滤器。

public class MyFilterAttribute : ActionFilterAttribute
{
    public override virtual void OnResultExecuting(ResultExecutingContext filterContext)
    {
        //...
    }
}

不推荐在内置属性中覆盖它,但您可以通过各种其他方式挂钩该方法。但如果你真的想这样做,MVC就是开源......

答案 4 :(得分:1)

您可以创建这样的扩展方法(请注意GetPlan() - 参数列表中的this-keyword):

public class CachePlanExtension //does not have to be static
{
    public static CacheSettings GetPlan(this CachePlan cachePlan, ControllerContext filterContext) //has to be static!
    {
        //the cachePlan-Parameter will later contain the CachePlan-object, on which you call this method. Example:
        var name = cachePlan.Name;


        CacheSettings ca = new CacheSettings();
        ca.IsCachingEnabled = true;
        ca.Duration = 100;
        return ca;
    }
}

每当你可以“看到”扩展类(这意味着它必须是公共的或内部的,并且你必须包括扩展类的命名空间)时,你可以调用这样的方法:

new CachePlan().GetPlan(filterContext);

答案 5 :(得分:0)

您可以在继承的类中覆盖该方法。