Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Invoking a Generic Method With Parameters using Reflection

0.00/5 (No votes)
30 Aug 2011CPOL 23.2K  
Sample use of generics and type retrieval
Context

Imagine that you have few lookup tables[^]. Each one can have its own lookup method; e.g.,
C#
string LookupCountryCodes(string query);
string LookupStateCodes(string query);
string LookupCardTypes(string query)

Likely, these methods differ only in the table /entity name that they apply to. Every time a new lookup table / entity is added, the lookup method has to be copied. Readability, extensibility, and maintainability of the code suffers.

Idea

Instead, we can define the lookup as a generic method[^]; e.g.,
C#
string Lookup<t>(string query) where T: class, ILookupEntity, new();
</t>


Then, given a table / entity name, we can find the associated:

  • table / entity type

C#
var t = Type.GetType(typeName);
if (t == null)
{
    var types = from assembly in System.AppDomain.CurrentDomain.GetAssemblies()
                from assemblyType in assembly.GetTypes()
                where assemblyType.Name == typeName
                select assemblyType;

    t = types.FirstOrDefault();
}


  • Lookup method

C#
var method = [owner_of_lookup_method].GetType()
    .GetMethod("Lookup", new Type[] {typeof (string)})
    .MakeGenericMethod(entityType);

where the [owner_of_Lookup_method] is either a static class or an instance of an object with a Lookup method definition.

Implementation

Putting it all together:
C#
private Dictionary<string,> typeCache = new Dictionary<string,>(); 

public bool TryFindType(string typeName, out Type t)
{
    lock (typeCache)
    {
        if (!typeCache.TryGetValue(typeName, out t))
        {
            t = Type.GetType(typeName);
            if (t == null)
            {
                var types = from assembly in System.AppDomain.CurrentDomain.GetAssemblies()
                            from assemblyType in assembly.GetTypes()
                            where assemblyType.Name == typeName
                            select assemblyType;

                t = types.FirstOrDefault();
            }
            typeCache[typeName] = t; // perhaps null
        }
    }
    return t != null;
}

public string Get(string entityTypeName, string query)
{
    Type entityType;

    if (TryFindType(entityTypeName, out entityType))
    {
        var method = [owner_of_lookup_method].GetType()
            .GetMethod("Lookup", new Type[] {typeof (string)})
            .MakeGenericMethod(entityType);

        return Convert.ToString(method.Invoke([owner_of_lookup_method], new[] { query }));
    }

    return string.Empty;
}


See also:
How to use reflection to call generic method[^]
GetType returns null[^]
GetType returns null (2)[^]
How to invoke method with parameters[^]
Object does not match target type+Reflection[^]
Overcoming problems with MethodInfo.Invoke of methods with by-reference value type arguments[^]

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)