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

本文关键字:方法 调用 何扩展 扩展 | 更新日期: 2023-09-27 18:16:41

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

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。想过吗?

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

您不能"进入"现有类并更改其方法的含义。这将是一个重大的安全漏洞。

您可以像这样创建一个扩展方法(注意GetPlan()参数列表中的this关键字):

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

简单地说;"不可能的"。如网页所述…

您可以使用扩展方法来扩展类或接口,但不能来推翻他们。具有相同名称和签名的扩展方法因为接口或类方法永远不会被调用。在编译时,扩展方法的优先级总是低于实例方法在类型本身中定义。换句话说,如果一个类型有一个方法命名为Process(int i),并且您有一个具有相同的扩展方法签名时,编译器将始终绑定到实例方法。当编译器遇到方法调用时,首先查找在类型的实例方法中进行匹配。如果没有找到匹配项,它将搜索为该类型定义的任何扩展方法,然后绑定到它找到的第一个扩展方法。

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

扩展方法只是编译成静态方法调用的语法糖。你可以写一个静态方法来完成同样的事情,你只是不能按你喜欢的方式调用它。如果方法是虚方法,则可以在派生类中重写它。只要确保始终实例化自己的类型即可。您也可以使用new关键字,但不会使用简单的强制转换和代码。最好是为自己创建一个简单的包装器类。该类将具有所讨论的类的实例,并找出正确的调用。这在创建特殊集合时非常常见,因为许多. net集合类型不适合继承。但最糟糕的是,你可以使用鼹鼠。

编辑

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

public class MyFilterAttribute : ActionFilterAttribute
{
    public override virtual void OnResultExecuting(ResultExecutingContext filterContext)
    {
        //...
    }
}
不建议在内置属性中重写

,但您可以通过各种其他方式钩入该方法。但是如果你真的想这样做,MVC是开源的…

您可以在继承的类中重写该方法。