如何为通用类型类编写 C# 扩展方法

11

这应该是一个简单的问题。

我想为System.Web.Mvc.ViewPage< T >类添加一个扩展方法。

这个扩展方法应该长什么样呢?

我的第一直觉是像这样:

namespace System.Web.Mvc
{
    public static class ViewPageExtensions
    {
        public static string GetDefaultPageTitle(this ViewPage<Type> v)
        {
            return "";
        }
    }
}

解决方案

通用的解决方案可以参考这个答案

如果需要扩展System.Web.Mvc.ViewPage类,则可以参考下面的我的回答,该回答是从通用解决方案开始的。

不同之处在于,在特定情况下,您需要同时声明一个泛型类型方法并强制将泛型类型作为引用类型。

7个回答

19

我当前的计算机上没有安装VS,但我认为语法应该是:

namespace System.Web.Mvc
{
    public static class ViewPageExtensions
    {
        public static string GetDefaultPageTitle<T>(this ViewPage<T> v)
        {
            return "";
        }
    }
}

请参见https://dev59.com/y3VD5IYBdhLWcg3wKYL-#68802。 - Matt Mitchell

6

感谢leddt。

执行这个操作会出现以下错误:

必须将类型“TModel”设置为引用类型,才能将其用作泛型类型或方法中的参数“TModel”

这指向了此页面,提供了以下解决方案:

namespace System.Web.Mvc
{
    public static class ViewPageExtensions
    {
        public static string GetDefaultPageTitle<T>(this ViewPage<T> v) 
          where T : class
        {
            return "";
        }
    }
}

3
它只需要在函数上使用通用类型说明符即可:

namespace System.Web.Mvc
{
    public static class ViewPageExtensions
    {
        public static string GetDefaultPageTitle<Type>(this ViewPage<Type> v)
        {
            return "";
        }
    }
}

编辑:只是在几秒钟之内错过了它!


2
namespace System.Web.Mvc
{
    public static class ViewPageExtensions
    {
        public static string GetDefaultPageTitle<T>(this ViewPage<T> view)
            where T : class
        {
            return "";
        }
    }
}

您可能还需要/愿意将"new()"限定符添加到泛型类型中(即"where T : class, new()"),以强制T既是引用类型(class),又具有无参数构造函数。


1
如果你希望扩展仅适用于指定类型,只需指定实际的处理类型即可。类似这样:...
public static string GetDefaultPageTitle(this ViewPage<YourSpecificType> v)
{
  ...
}

请注意,当您使用匹配类型声明(在本例中为)ViewPage时,智能感知功能将仅显示扩展方法。

此外,最好不要使用System.Web.Mvc命名空间。我知道在usings部分中不必包含您的命名空间很方便,但如果您为扩展函数创建自己的扩展命名空间,则更易于维护。


1

Glenn Block有一个很好的示例,演示如何实现一个ForEach扩展方法用于IEnumerable<T>

来自他的博客文章

public static class IEnumerableUtils
{
    public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
    {
        foreach(T item in collection)
            action(item);
    }
}

1

以下是 Razor 视图的示例:

public static class WebViewPageExtensions
{
    public static string GetFormActionUrl(this WebViewPage view)
    {
        return string.Format("/{0}/{1}/{2}", view.GetController(), view.GetAction(), view.GetId());
    }

    public static string GetController(this WebViewPage view)
    {
        return Get(view, "controller");
    }

    public static string GetAction(this WebViewPage view)
    {
        return Get(view, "action");
    }

    public static string GetId(this WebViewPage view)
    {
        return Get(view, "id");
    }

    private static string Get(WebViewPage view, string key)
    {
        return view.ViewContext.Controller.ValueProvider.GetValue(key).RawValue.ToString();
    }
}

你真的不需要使用泛型版本,因为泛型版本扩展了非泛型版本,所以只需将它放入非泛型基类中即可完成 :)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接