Como você escreve um método de extensão C# para uma classe de tipo genérico
-
09-06-2019 - |
Pergunta
Esperançosamente, isso deve ser simples.
Gostaria de adicionar um método de extensão à classe System.Web.Mvc.ViewPage< T >.
Como deve ser esse método de extensão?
Meu primeiro pensamento intuitivo é mais ou menos assim:
namespace System.Web.Mvc
{
public static class ViewPageExtensions
{
public static string GetDefaultPageTitle(this ViewPage<Type> v)
{
return "";
}
}
}
Solução
A solução geral é esta resposta.
A solução específica para estender a classe System.Web.Mvc.ViewPage é minha resposta abaixo, que começou a partir do solução geral.
A diferença está no caso específico de que você precisa de uma declaração de método de tipo genérico E de uma instrução para impor o tipo genérico como um tipo de referência.
Solução
Não tenho o VS instalado na minha máquina atual, mas acho que a sintaxe seria:
namespace System.Web.Mvc
{
public static class ViewPageExtensions
{
public static string GetDefaultPageTitle<T>(this ViewPage<T> v)
{
return "";
}
}
}
Outras dicas
Obrigado, Leddt.Fazer isso gerou o erro:
O tipo 'tmodel' deve ser um tipo de referência para usá -lo como parâmetro 'tmodel' no tipo ou método genérico
que me indicou esta página, que rendeu esta solução:
namespace System.Web.Mvc
{
public static class ViewPageExtensions
{
public static string GetDefaultPageTitle<T>(this ViewPage<T> v)
where T : class
{
return "";
}
}
}
Ele só precisa do especificador de tipo genérico na função:
namespace System.Web.Mvc
{
public static class ViewPageExtensions
{
public static string GetDefaultPageTitle<Type>(this ViewPage<Type> v)
{
return "";
}
}
}
Editar:Só perdi por segundos!
namespace System.Web.Mvc
{
public static class ViewPageExtensions
{
public static string GetDefaultPageTitle<T>(this ViewPage<T> view)
where T : class
{
return "";
}
}
}
Você também pode precisar/desejar adicionar o qualificador "new()" ao tipo genérico (ou seja,"onde T:class, new()" para garantir que T é um tipo de referência (classe) e possui um construtor sem parâmetros.
Glenn Block tem um bom exemplo de implementação de um ForEach
método de extensão para IEnumerable<T>
.
Dele postagem no blog:
public static class IEnumerableUtils
{
public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
{
foreach(T item in collection)
action(item);
}
}
Se você deseja que a extensão esteja disponível apenas para o tipo especificado, você simplesmente precisa especificar o tipo real que você estará lidando
algo como...
public static string GetDefaultPageTitle(this ViewPage<YourSpecificType> v)
{
...
}
Observe que o intellisense exibirá apenas o método de extensão quando você declarar sua (neste caso) ViewPage com o tipo correspondente.
Além disso, é melhor não usar o namespace System.Web.Mvc, sei que é conveniente não precisar incluir seu namespace na seção de usos, mas é muito mais fácil de manter se você criar seu próprio namespace de extensões para suas funções de extensão.
Aqui está um exemplo para visualizações do 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();
}
}
Você realmente não precisa usar a versão genérica, pois a genérica estende a não genérica, então basta colocá-la na classe base não genérica e pronto :)