Como chamar um método genérico por Type em C#: tutorial claro

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: quando o código diz "não sei"

\n

Imagine a situação: você está escrevendo uma biblioteca de serialização em C#. Você tem o método Serialize<T>(T obj), que consegue transformar qualquer objeto em uma string. Tudo funciona perfeitamente enquanto você o chama com um tipo específico: Serialize<User>(user). Mas o que fazer quando o tipo do objeto só é conhecido durante a execução do programa?

\n\n

Este é um problema clássico que milhares de desenvolvedores perguntam no Stack Overflow: "How do I call a generic method using a Type variable?". À primeira vista, a solução parece simples, mas C# é uma linguagem fortemente tipada, e simplesmente colocar uma variável de tipo entre colchetes angulares não funciona.

\n\n

Neste tutorial, vamos abordar como chamar corretamente métodos genéricos através da reflexão em C# usando MakeGenericMethod. Você aprenderá não apenas a sintaxe, mas também quando isso é realmente necessário e quando é melhor buscar alternativas.

\n\n

Por que não podemos simplesmente escrever Method<type>()?

\n

Vamos acabar com as ilusões imediatamente. O código a seguir não compila:

\n
Type runtimeType = someObject.GetType();\n// Erro de compilação: "O tipo 'runtimeType' não é válido"\nSomeMethod<runtimeType>();\n
\n\n

Por quê? Porque parâmetros genéricos em C# são metadados de tempo de compilação. O compilador precisa saber exatamente com qual tipo está trabalhando para gerar o código. A variável Type é um objeto que existe apenas em tempo de execução. Para o compilador, é apenas uma variável, não um tipo.

\n\n

A solução está na área da reflexão — um mecanismo que permite inspecionar e invocar membros de tipos durante a execução.

\n\n

Tutorial passo a passo: chamando um método genérico através de Type

\n

Vamos analisar o problema com um exemplo concreto. Suponha que temos um serviço para processamento de dados:

\n
public class DataProcessor\n{\n    public string Process<T>(T data)\n    {\n        return $"Processado {typeof(T).Name}: {data}";\n    }\n}\n
\n\n

Queremos chamar Process<T> quando o tipo T é conhecido apenas em tempo de execução, por exemplo, a partir de typeof(string) ou someObject.GetType().

\n\n

Passo 1. Obtendo o MethodInfo para o método genérico

\n

Primeiro, precisamos obter o objeto que representa nosso método:

\n
DataProcessor processor = new DataProcessor();\nType processorType = typeof(DataProcessor);\n\n// Procuramos o método pelo nome. Importante: especificar BindingFlags se o método não for public\nMethodInfo? methodInfo = processorType.GetMethod("Process");\n
\n\n

Importante! Se você tiver várias sobrecargas do método, precisará refinar a busca usando GetMethods() e filtragem. No nosso caso, há apenas um método — é simples.

\n\n

Passo 2. Transformando o método genérico em um método concreto com MakeGenericMethod

\n

Aqui está, o protagonista do artigo — o método MakeGenericMethod. Ele recebe um array de tipos e retorna um método construído (concreto):

\n
Type runtimeType = typeof(int); // ou qualquer outro tipo obtido dinamicamente\nMethodInfo? genericMethod = methodInfo?.MakeGenericMethod(runtimeType);\n
\n\n

Agora, genericMethod é um método completo Process<int>, pronto para ser chamado.

\n\n

Passo 3. Chamando o método através de Invoke

\n

O toque final — usar Invoke:

\n
object? result = genericMethod?.Invoke(processor, new object[] { 42 });\nConsole.WriteLine(result); // Exibirá: "Processado Int32: 42"\n
\n\n

Observe:

\n
    \n
  • O primeiro parâmetro de Invoke é a instância do objeto (para métodos estáticos — null).
  • \n
  • O segundo parâmetro é um array de argumentos do método. Mesmo que haja apenas um argumento, ele deve estar em um array.
  • \n
  • O resultado é retornado como object? — você pode gostar

Blogs

Book Recommendations