Как вы пишете метод расширения C # для обобщенно типизированного класса
-
09-06-2019 - |
Вопрос
Надеюсь, это должно быть простым решением.
Я хотел бы добавить метод расширения к 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 является мой ответ ниже, который начинался с общее решение.
Разница заключается в конкретном случае, когда вам нужно как объявление обобщенно типизированного метода, так И оператор для принудительного применения универсального типа в качестве ссылочного типа.
Решение
У меня не установлен VS на моем текущем компьютере, но я думаю, что синтаксис будет следующим:
namespace System.Web.Mvc
{
public static class ViewPageExtensions
{
public static string GetDefaultPageTitle<T>(this ViewPage<T> v)
{
return "";
}
}
}
Другие советы
Спасибо, леддт.Выполнение этого привело к ошибке:
Тип 'tModel' должен быть ссылочным тип, чтобы использовать его в качестве параметра 'tModel' в универсальном типе или методе
который указал мне на эта страница, что привело к такому решению:
namespace System.Web.Mvc
{
public static class ViewPageExtensions
{
public static string GetDefaultPageTitle<T>(this ViewPage<T> v)
where T : class
{
return "";
}
}
}
Ему просто нужен спецификатор универсального типа для функции:
namespace System.Web.Mvc
{
public static class ViewPageExtensions
{
public static string GetDefaultPageTitle<Type>(this ViewPage<Type> v)
{
return "";
}
}
}
Редактировать:Просто промахнулся на несколько секунд!
namespace System.Web.Mvc
{
public static class ViewPageExtensions
{
public static string GetDefaultPageTitle<T>(this ViewPage<T> view)
where T : class
{
return "";
}
}
}
Вам также может понадобиться / пожелать добавить квалификатор "new()" к универсальному типу (т. е."где Т :class, new()" для обеспечения того, чтобы T был одновременно ссылочным типом (class) и имел конструктор без параметров.
Гленн Блок имеет хороший пример реализации 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);
}
}
Если вы хотите, чтобы расширение было доступно только для указанного типа вам просто нужно указать фактический тип, с которым вы будете работать
что-то вроде...
public static string GetDefaultPageTitle(this ViewPage<YourSpecificType> v)
{
...
}
Примечание. intellisense будет отображать метод расширения только тогда, когда вы объявите свою (в данном случае) страницу просмотра с соответствующим типом.
Кроме того, лучше не использовать пространство имен System.Web.Mvc, я знаю, что удобно не включать ваше пространство имен в раздел usings, но его гораздо удобнее обслуживать, если вы создадите свое собственное пространство имен extensions для своих функций расширения.
Вот пример для просмотра 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();
}
}
Вам действительно не нужно использовать универсальную версию, поскольку универсальная расширяет непатентованную, поэтому просто поместите ее в непатентованный базовый класс, и все готово :)