Как вы пишете метод расширения С# для универсально типизированного класса

Надеюсь, это должно быть просто.

Я хотел бы добавить метод расширения в класс 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 является мой ответ ниже, который начался с общее решение.

Разница заключается в том, что в конкретном случае вам нужно как объявление метода универсального типа, так и оператор для принудительного применения универсального типа в качестве ссылочного типа.


person Matt Mitchell    schedule 16.09.2008    source источник


Ответы (7)


У меня не установлен VS на моем текущем компьютере, но я думаю, что синтаксис будет таким:

namespace System.Web.Mvc
{
    public static class ViewPageExtensions
    {
        public static string GetDefaultPageTitle<T>(this ViewPage<T> v)
        {
            return "";
        }
    }
}
person David Thibault    schedule 16.09.2008
comment
См. stackoverflow.com/questions/68750/ - person Matt Mitchell; 06.09.2009

Спасибо леддт. Выполнение этого привело к ошибке:

Тип «TModel» должен быть ссылочным типом, чтобы использовать его в качестве параметра «TModel» в универсальном типе или методе.

который указал мне на эту страницу, что дало следующее решение:

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

Ему просто нужен спецификатор универсального типа для функции:

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

Редактировать: просто пропустил это на несколько секунд!

person Corey Ross    schedule 16.09.2008

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 был одновременно ссылочным типом (классом) и имел конструктор без параметров.

person chadmyers    schedule 16.09.2008

У Гленна Блока есть хороший пример реализации метода расширения 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);
    }
}
person Eric Schoonover    schedule 16.09.2008

Если вы хотите, чтобы расширение было доступно только для указанного типа, вам просто нужно указать фактический тип, с которым вы будете работать.

что-то типа...

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

Обратите внимание, что intellisense будет отображать только метод расширения, когда вы объявляете свою (в данном случае) ViewPage с соответствующим типом.

Кроме того, лучше не использовать пространство имен System.Web.Mvc, я знаю, что удобно не включать ваше пространство имен в раздел использования, но его гораздо удобнее поддерживать, если вы создаете собственное пространство имен расширений для своих функций расширения.

person Tim Jarvis    schedule 16.09.2008

Вот пример для представлений 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();
    }
}

Вам действительно не нужно использовать универсальную версию, поскольку универсальная версия расширяет неуниверсальную, поэтому просто поместите ее в неуниверсальный базовый класс, и все готово :)

person Tod Thomson    schedule 02.08.2012