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

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

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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
11
0
12 759
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Ответ принят как подходящий

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

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

См. stackoverflow.com/questions/68750/…

Matt Mitchell 06.09.2009 17:28

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

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

Обновлено: просто пропустил секунды!

Спасибо, leddt. Это привело к ошибке:

The type 'TModel' must be a reference type in order to use it as parameter 'TModel' in the generic type or method

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

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

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

что-то вроде...

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

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

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

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

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

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

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

Другие вопросы по теме