.NET Pro tips - Métodos de Extensão
Esse artigo faz parte de uma série de artigos sobre como utilizar o EFCore com múltiplos providers de banco de dados. Se quiser veja outras partes dessa série em links relacionados.
O que isso quer dizer?
Métodos de extensão, como o próprio nome diz, adiciona extensões a objetos existentes, evitando alterar códigos existentes (o que facilmente leva a introdução de bugs e complexidade na escrita e leitura de novos códigos)
Perceba a contribução para os princípios Single Responsibility e Open/Closed do SOLID e com isso atingimos um bom Clean Code.
Um exemplo simples de utilização seria transformar um texto para algumas convenções de nomenclatura como o CamelCase.
Nesse exemplo não temos acesso direto à classe string
o que já nos impediria de adicionar um método novo a essa classe.
Um exemplo de implementação seria:
var myText = "Hello World";
var myTextCamelCase = (char.ToLowerInvariant(str[0]) + str.Substring(1))
.Replace(" ", string.Empty);
_logger.LogInformation(myText + " ToCamelCase -> " + myText.ToCamelCase());
// Output -> Hello World ToCamelCase -> helloWorld
Porém isso nos leva a ter que repetir a implementação em qualquer lugar (o que fere o conceito DRY). Além de ferir conceitos e princípios temos o problema de falta de clareza no código dificultando a leitura.
Os métodos de extensão nos ajuda da seguinte forma:
public static class StringExtension
{
public static string ToCamelCase(this string str)
{
if(!string.IsNullOrEmpty(str) && str.Length > 1)
{
return (char.ToLowerInvariant(str[0]) + str.Substring(1)).Replace(" ", string.Empty);
}
return str;
}
}
O que indica ser um método de extensão não é o suffixo
Extension
no nome da classe e sim a palavra reservadathis
antes do primeiro parâmetro e a característica estática.
Assim podemos reutilizar em diversos lugares, apenas utilizando a chamada de um método.
var myText = "Hello World";
var myTextCamelCase = myText.ToCamelCase();
Console.WriteLn(myTextCamelCase);
Note que na chamada do método não existe parâmetro. O parâmtro é a própria variável do tipo string. Note também que a leitura é facilitada.
Com a utilização de métodos de extensão podemos reaproveitar código e organizar de forma lógica dentro da nossa aplicação.
Seguindo nessa mesma lógica podemos alterar no ssa classe e atribuir outras convenções de nomes, nesse caso irei renomear a classe e adicionar métodos para snake case e pascal case
using System.Linq;
namespace Helpers.Extensions.String
{
public static class NamingConventionExtension
{
public static string ToCamelCase(this string str)
{
if (!string.IsNullOrEmpty(str) && str.Length > 1)
return (char.ToLowerInvariant(str[0]) + str.Substring(1)).Replace(" ", string.Empty);
return str;
}
public static string ToSnakeCase(this string str)
{
return str?.ToLower().Replace(" ", "_");
}
public static string ToPascalCase(this string str)
{
return string.Join("", str.Split('_')
.Select(w => w.Trim())
.Where(w => w.Length > 0)
.Select(w => w.Substring(0, 1).ToUpper() + w.Substring(1).ToLower()));
}
}
}
Utilização:
var myText = "Hello World";
_logger.LogInformation(myText + " ToCamelCase -> " + myText.ToCamelCase());
// Output -> Hello World ToCamelCase -> helloWorld
_logger.LogInformation(myText + " ToPascalCase -> " + myText.ToPascalCase());
// Output -> Hello World ToPascalCase -> HelloWorld
_logger.LogInformation(myText + " ToSnakeCase -> " + myText.ToSnakeCase());
// Output -> Hello World ToSnakeCase -> hello_world
Nesse caso a implementação do método está em um projeto auxiliar denomidado Helpers. Isso nos obriga a adicionar using Helpers.Extensions.String;
Minha prioridade aqui não foi mostrar uma implentação perfeita dos métodos, apenas de como utilizar os métodos de extensão.
Os métodos de extensão nos ajudam a organizar nosso código por toda a nossa solução. Agrupando responsabilidades ao projeto apropriado.
Agora com nosso código encapsulado podemos melhorar sem precisar alterar a chamada.
Fique a vontade para implementar a sua versão.