Question

Call a Generic Method with a Runtime Type in C#

csharp.netgenericsreflection

Question

In C#, how can you call a generic method when the type argument is not known at compile time, but is instead determined dynamically at runtime?

For example, in the following code, the Example() method gets a Type object from FindType(typeName). What is the correct and concise way to call GenericMethod<T>() using the type stored in myType?

How would the approach differ for calling the static method StaticMethod<T>()?

public class Sample
{
    public void Example(string typeName)
    {
        Type myType = FindType(typeName);

        // How do we call GenericMethod<T>() here?
        // GenericMethod<myType>(); // This does not compile

        // How do we call StaticMethod<T>() here?
        // Sample.StaticMethod<myType>(); // This also does not compile
    }

    public void GenericMethod<T>()
    {
        // ...
    }

    public static void StaticMethod<T>()
    {
        // ...
    }
}

Short Answer

By the end of this page, you will understand why GenericMethod<myType>() does not compile in C#, and how to call a generic method when the type is only known at runtime. You will learn how to use reflection with GetMethod(), MakeGenericMethod(), and Invoke() for both instance and static generic methods, along with common mistakes and practical patterns used in real codebases.

Concept

In C#, generic type arguments such as T are normally chosen at compile time. That means code like this works:

GenericMethod<int>();

because int is a known type when the code is compiled.

But this does not work:

Type myType = typeof(int);
GenericMethod<myType>();

The reason is that myType is a variable, not a type name in source code. C# generic syntax requires an actual type at compile time, not a Type object stored in memory.

When the type is only available at runtime, the usual solution is reflection.

The key reflection steps are:

  1. Find the generic method definition.
  2. Create a closed generic version of that method using MakeGenericMethod(runtimeType).
  3. Invoke the method.

Example idea:

MethodInfo method = typeof(Sample).GetMethod(nameof(GenericMethod));
MethodInfo closedMethod = method.MakeGenericMethod(myType);
closedMethod.Invoke(this, null);

This matters in real programs because runtime-selected types appear often:

  • serializers and deserializers
  • dependency injection frameworks
  • plugin systems
  • object mappers
  • generic repositories
  • data conversion utilities

Whenever code must adapt to types discovered dynamically, reflection is one of the main tools used.

Mental Model

Think of a generic method like a template machine.

  • GenericMethod<int>() means: “build the machine configured for int.”
  • GenericMethod<string>() means: “build the machine configured for string.”

At compile time, C# wants you to say exactly which machine you want.

A Type variable is more like a note in your hand that says which machine to build later. The compiler cannot use that note directly in generic syntax. Instead, reflection acts like a factory worker who reads the note at runtime and builds the correct version of the machine for you.

So:

  • generic syntax (<int>) = compile-time choice
  • Type object (typeof(int) or runtime result) = runtime choice
  • reflection = bridge between the two
Take Quiz

Syntax and Examples

Core syntax

To call a generic method using a runtime Type in C#, use reflection:

MethodInfo method = typeof(Sample).GetMethod(nameof(GenericMethod));
MethodInfo closedMethod = method.MakeGenericMethod(myType);
closedMethod.Invoke(this, null);

For a static generic method:

MethodInfo method = typeof(Sample).GetMethod(nameof(StaticMethod));
MethodInfo closedMethod = method.MakeGenericMethod(myType);
closedMethod.Invoke(null, null);

Complete example

using System;
using System.Reflection;

public class Sample
{
    public void Example(string typeName)
    {
        Type myType = FindType(typeName);

        MethodInfo instanceMethod = typeof(Sample).GetMethod(nameof(GenericMethod));
        MethodInfo closedInstanceMethod = instanceMethod.MakeGenericMethod(myType);
        closedInstanceMethod.Invoke(this, null);

        MethodInfo staticMethod = typeof(Sample).GetMethod(nameof(StaticMethod));
        MethodInfo closedStaticMethod = staticMethod.MakeGenericMethod(myType);
        closedStaticMethod.Invoke(null, null);
    }

    public void GenericMethod<T>()
    {
        Console.WriteLine($"Instance generic method called with {typeof(T).Name}");
    }

    public static void StaticMethod<T>()
    {
        Console.WriteLine($"Static generic method called with {typeof(T).Name}");
    }

    private Type FindType(string typeName)
    {
        return typeName switch
        {
            "int" => typeof(int),
            "string" => typeof(string),
            _ => typeof(object)
        };
    }
}

What this example does

  • GetMethod() finds the method definition.
  • MakeGenericMethod(myType) creates a version like GenericMethod<int>() or GenericMethod<string>().
  • Invoke() runs it.
  • For instance methods, pass this as the target.
  • For static methods, pass null as the target.

Step by Step Execution

Traceable example

using System;
using System.Reflection;

public class Sample
{
    public void Example()
    {
        Type myType = typeof(string);

        MethodInfo method = typeof(Sample).GetMethod(nameof(GenericMethod));
        MethodInfo closedMethod = method.MakeGenericMethod(myType);
        closedMethod.Invoke(this, null);
    }

    public void GenericMethod<T>()
    {
        Console.WriteLine(typeof(T).FullName);
    }
}

Step by step

1. myType is assigned

Type myType = typeof(string);

Now myType stores the runtime type System.String.

2. The generic method definition is found

MethodInfo method = typeof(Sample).GetMethod(nameof(GenericMethod));

This gets metadata for the open generic method GenericMethod<T>().

3. A closed generic version is created

MethodInfo closedMethod = method.MakeGenericMethod(myType);

This produces the equivalent of:

GenericMethod<string>()

but built dynamically at runtime.

4. The method is invoked

closedMethod.Invoke(this, null);
  • this means call the method on the current object.
  • null means there are no normal method arguments.

5. The method runs

Inside the method:

Console.WriteLine(typeof(T).FullName);

Since T became string, the output is:

System.String

Real World Use Cases

Where this is used

Serializers

A serializer may discover the target type at runtime and need to call a generic method like:

Deserialize<T>()

Dependency injection containers

A DI framework may resolve services from a Type object and internally build calls to generic methods such as:

Resolve<T>()

Mapping libraries

Object mappers often receive source and destination types dynamically and may call generic conversion methods behind the scenes.

Plugin systems

A plugin loader might inspect assemblies, find types, and invoke generic registration methods based on discovered classes.

Data access helpers

A repository may need to call methods like:

GetEntity<T>()

when T comes from configuration, metadata, or reflection.

Testing tools and frameworks

Unit testing frameworks often discover test classes and invoke generic helper methods using runtime type information.

Take Quiz

Real Codebase Usage

Common patterns in real projects

Guard clauses before reflection

Reflection can fail if the method is not found or the type is invalid. Real code often validates early:

if (myType == null)
    throw new ArgumentNullException(nameof(myType));

MethodInfo method = typeof(Sample).GetMethod(nameof(GenericMethod))
    ?? throw new InvalidOperationException("Method not found.");

Caching MethodInfo

Reflection is slower than direct calls. In production code, developers often cache method metadata:

private static readonly MethodInfo GenericMethodDefinition =
    typeof(Sample).GetMethod(nameof(GenericMethod));

Then reuse it instead of calling GetMethod() repeatedly.

Wrapping reflection in helper methods

Teams usually avoid scattering reflection code everywhere. Instead, they create a helper:

public void CallGeneric(Type type)
{
    MethodInfo method = typeof(Sample).GetMethod(nameof(GenericMethod));
    MethodInfo closed = method.MakeGenericMethod(type);
    closed.Invoke(this, null);
}

Validation for generic constraints

If the generic method has constraints, code may validate them before calling MakeGenericMethod().

Error handling around Invoke

Invoke() may wrap exceptions in TargetInvocationException. Real code often unwraps or logs the inner exception.

Prefer non-reflection alternatives when possible

If the set of types is known, developers often use:

  • switch on known types
  • dictionaries of delegates
  • interfaces or polymorphism

Reflection is usually chosen only when runtime flexibility is truly needed.

Common Mistakes

1. Trying to use a Type variable in generic syntax

This does not compile:

Type myType = typeof(int);
GenericMethod<myType>();

Why

Generic angle-bracket syntax expects a compile-time type, not a variable.

Fix

Use reflection:

MethodInfo method = typeof(Sample).GetMethod(nameof(GenericMethod));
MethodInfo closed = method.MakeGenericMethod(myType);
closed.Invoke(this, null);

2. Passing the wrong target to Invoke()

Broken code for an instance method:

closedMethod.Invoke(null, null);

Why

Instance methods need an object instance.

Fix

Use this or another object instance:

closedMethod.Invoke(this, null);

For static methods, null is correct.

3. Forgetting method arguments

If the method has parameters, they must be passed in the second argument array.

Broken example:

public void PrintValue<T>(T value) { }

closedMethod.Invoke(this, null);

Fix

Pass the arguments:

closedMethod.Invoke(this, new object[] { "hello" });

4. Using GetMethod() when there are overloads

If multiple methods have the same name, GetMethod(nameof(GenericMethod)) may not return the one you expect.

Fix

Use overload-specific lookup or filter the methods:

MethodInfo method = typeof(Sample)
    .GetMethods()
    .First(m => m.Name == nameof(GenericMethod) && m.IsGenericMethodDefinition);

5. Ignoring generic constraints

If a method is declared like this:

public void GenericMethod<T>() where T : class, new()

then not every runtime type is valid.

Fix

Make sure myType satisfies the constraints before calling MakeGenericMethod().

6. Not checking for null

Broken code:

MethodInfo method = typeof(Sample).GetMethod("MissingMethod");
MethodInfo closed = method.MakeGenericMethod(myType);

Why

If GetMethod() returns null, the next line crashes.

Fix

Check first:

MethodInfo method = typeof(Sample).GetMethod(nameof(GenericMethod))
    ?? throw new InvalidOperationException("GenericMethod not found.");

Comparisons

Generic call at compile time vs runtime

ApproachWhen it worksExampleProsCons
Direct generic callType is known at compile timeGenericMethod<int>()Fast, simple, type-safeCannot use runtime Type values
Reflection with MakeGenericMethodType is only known at runtimemethod.MakeGenericMethod(myType).Invoke(...)Flexible, works with dynamic type discoveryMore verbose, less type-safe, slower

Instance vs static generic method invocation

Method kindTarget passed to Invoke()Example
Instance methodObject instanceclosed.Invoke(this, null)
Static methodnullclosed.Invoke(null, null)

Reflection vs alternative designs

OptionBest forExample ideaTradeoff
ReflectionUnknown types discovered at runtimeplugins, serializersFlexible but slower and more complex
switch on known typesSmall known set of typesif (type == typeof(int))Easy to read, but not scalable
Dictionary of delegatesKnown runtime mappingsDictionary<Type, Action>Faster than reflection, but only for predefined types
Interfaces/polymorphismBehavior attached to objectshandler.Handle()Cleaner OO design, but not useful if all you have is a Type

MakeGenericMethod vs MakeGenericType

APIUsed forExample
MakeGenericMethodGeneric methodsmethod.MakeGenericMethod(typeof(string))
MakeGenericTypeGeneric classes/typestypeof(List<>).MakeGenericType(typeof(string))
Take Quiz

Cheat Sheet

Quick reference

Direct generic call

GenericMethod<int>();

Use this when the type is known at compile time.

Runtime generic call

MethodInfo method = typeof(Sample).GetMethod(nameof(GenericMethod));
MethodInfo closed = method.MakeGenericMethod(myType);
closed.Invoke(this, null);

Static runtime generic call

MethodInfo method = typeof(Sample).GetMethod(nameof(StaticMethod));
MethodInfo closed = method.MakeGenericMethod(myType);
closed.Invoke(null, null);

Rules

  • GenericMethod<myType>() is invalid because myType is a variable, not a compile-time type.
  • Use MakeGenericMethod() for generic methods.
  • Use MakeGenericType() for generic classes/types.
  • Pass an object instance to Invoke() for instance methods.
  • Pass null to Invoke() for static methods.
  • If the method has parameters, pass them as object[].
  • Check for null from GetMethod().
  • Be careful with overloaded methods.
  • Generic constraints still apply at runtime.

Common pattern

MethodInfo method = typeof(MyClass).GetMethod(nameof(MyMethod))
    ?? throw new InvalidOperationException("Method not found.");

MethodInfo closed = method.MakeGenericMethod(runtimeType);
closed.Invoke(targetInstance, arguments);

FAQ

How do I call a generic method when I only have a Type object in C#?

Use reflection: find the method with GetMethod(), create a closed generic method with MakeGenericMethod(type), then call Invoke().

Why does GenericMethod<myType>() not compile?

Because C# generic syntax requires a type known at compile time. myType is a variable holding a Type value at runtime.

How do I invoke a static generic method with reflection?

Use the same reflection steps, but pass null as the target in Invoke().

What is the difference between MakeGenericMethod and MakeGenericType?

MakeGenericMethod is for generic methods. MakeGenericType is for generic classes or other generic types.

Is reflection the only way to do this?

If the type is truly unknown until runtime, reflection is the standard approach. If the possible types are known ahead of time, a switch, delegate map, or polymorphic design may be better.

Is calling generic methods with reflection slow?

It is slower than a direct method call. In many applications this is acceptable, but repeated reflection calls are often cached.

What happens if the generic method has constraints?

The runtime type must satisfy those constraints. Otherwise, MakeGenericMethod() or invocation will fail.

Can I call a generic method with parameters this way?

Yes. Pass normal method arguments as an object[] in Invoke() after creating the closed generic method.

Take Quiz

Mini Project

Description

Build a small runtime type invoker that accepts a type name like "int", "string", or "DateTime", converts it into a Type, and then calls both an instance generic method and a static generic method using that runtime type. This demonstrates the exact reflection pattern used when generic arguments are discovered dynamically.

Goal

Create a C# class that finds a runtime type from a string and invokes ShowType<T>() and ShowStaticType<T>() using reflection.

Requirements

  • Create a method that converts a type name string into a Type.
  • Add one instance generic method and one static generic method.
  • Use reflection to call both methods with the runtime type.
  • Print the selected type name from inside each generic method.
  • Handle the case where the type name is unknown.
Take Quiz

Keep learning

Related questions

View more