【问题标题】:How do you write a C# Extension Method for a Generically Typed Class如何为泛型类编写 C# 扩展方法
【发布时间】:2010-09-09 06:50:33
【问题描述】:

希望这应该是一个简单的。

我想在 System.Web.Mvc.ViewPage 类中添加一个扩展方法。

这个扩展方法应该怎么看?

我的第一个直觉想法是这样的:

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

解决方案

一般的解决方案是this answer

扩展System.Web.Mvc.ViewPage类的具体方案是下面的my answer,从general solution开始。

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

【问题讨论】:

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


    【解决方案1】:

    我当前的机器上没有安装 VS,但我认为语法是:

    namespace System.Web.Mvc
    {
        public static class ViewPageExtensions
        {
            public static string GetDefaultPageTitle<T>(this ViewPage<T> v)
            {
                return "";
            }
        }
    }
    
    【解决方案2】:

    谢谢leddt。 这样做会产生错误:

    类型“TModel”必须是引用 键入以将其用作参数 泛型类型或方法中的“TModel”

    这将我指向this page,它产生了这个解决方案:

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

      编辑:只是错过了几秒钟!

      【讨论】:

        【解决方案4】:
        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 既是引用类型(类)又具有无参数构造函数。

        【讨论】:

          【解决方案5】:

          Glenn Block 有一个很好的例子来实现ForEach 扩展方法到IEnumerable&lt;T&gt;

          来自他的blog post

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

          【讨论】:

            【解决方案6】:

            如果您希望扩展仅适用于指定类型 你只需要指定你将要处理的实际类型

            类似...

            public static string GetDefaultPageTitle(this ViewPage<YourSpecificType> v)
            {
              ...
            }
            

            注意,智能感知将仅在您声明(在本例中)具有匹配类型的 ViewPage 时显示扩展方法。

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

            【讨论】:

              【解决方案7】:

              这是 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();
                  }
              }
              

              您确实不需要使用通用版本,因为通用版本扩展了非通用版本,因此只需将其放入非通用基类中即可:)

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2011-06-23
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2019-10-18
                • 2014-12-21
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多