65.9K
CodeProject is changing. Read more.
Home

Invoking a Generic Method With Parameters using Reflection

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0 vote)

Aug 31, 2011

CPOL
viewsIcon

23227

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.,
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.,
string Lookup(string query) where T: class, ILookupEntity, new();
Then, given a table / entity name, we can find the associated:
  • table / entity type
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
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:
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[^]