0

I'm using .Net framework 2.0 to try and do the following:

I've an external service which returns a list of int. In turn I use each int to find a corresponding Type which has an Attribute with a property, key; the value of that property matches the search parameter.

Using the Type t I'd like to call a generic method, but I'm unable to do this. As I will only know the Type at runtime, I suspect I may have to use reflection to invoke the generic method GetResultsForType - is this the correct way to go about this?

[MyAttribute(key1 = 1)]
class A{
    //some properties
}

[MyAttribute(key1 = 2)]
class B{
    //some properties
}

//and so on (for hundreds of classes).  The key is unique for every class.

public class Foo{
    public void DoSomething(){
         IList<int> keys = QuerySomeExternalService();

         Assembly asm = LoadAssemblyFromSomewhere();
         Type[] types = asm.GetTypes();
         foreach(int key in keys){
             Type t = SearchTypesForAttributeWithMatchingKey(types, key);  //I omitted caching of all the keys and Types into a Dictionary on first iteration for brevity.
             IList<t> results = GetResultsForType<t>(); //won't work!
             //do something with the results
         }
    }

    Type SearchTypesForAttributeWithMatchingKey(Type[] types, int key){
        foreach(Type t in types){
            object[] attributes = t.GetCustomAttributes(typeof(MyAttribute),false);
            MyAttribute myAtt = attributes[0] as MyAttribute;
            if(myAtt.Key == key) return t;
        }
    }

    IList<T> GetResultsForType<T>(){
        IList<T> results = new List<T>();
        bool querySuccess = true;
        while(querySuccess){
            T result;
            querySuccess = QueryExternalService<T>(out result);
            results.Add(result);
        }
        return results;
    }
}
Iain Sproat
  • 5,210
  • 11
  • 48
  • 68
  • 2
    This is pretty similar to your last question (http://stackoverflow.com/questions/4661211/c-instantiate-generic-list-from-reflected-type), where you're using an instance of `System.Type` in place of a type param to invoke a generic method. I know you didn't really ask for architectural advice, but if you have to fight the type system left and right, it indicates something wrong with your design. I'd personally be interested to know what sort of problem you're actually trying to solve here, as opposed to *how* you're trying to solve it, maybe someone can suggest a cleaner way. – Juliet Jan 11 '11 at 19:42

1 Answers1

5

Yes you have to use reflection to call a generic method using a System.Type rather than a generic parameterization. You can use the method on methodInfo MakeGenericMethod(params Type[]) after finding the generic method.

If you know the method is called often but with a small number of types, you can cache delegates to invoke the right version.

Something like::

typeof(Foo).GetMethod("YourMethod").MakeGenericMethod(type).Invoke(new[]{parameters});
Michael B
  • 7,512
  • 3
  • 31
  • 57