3

There is a third-party component library like this:

 public static class GenericExcuteTestClassExtension
 {
    public static void Excute<T>(this GenericExcuteTestClass clazz,
                             string parameter, Action<ReturnClass<T>> callback)
    {
        ReturnClass<T> rClazz = new ReturnClass<T>(parameter);
        rClazz.Property5 = typeof(T).ToString();
        callback.Invoke(rClazz);
    }

    public static void Excute<T>(this GenericExcuteTestClass clazz,
                               string parameter, Action<ReturnClass> callback)
    {
        ReturnClass rClazz = new ReturnClass(parameter);
        rClazz.Property5 = typeof(T).ToString();
        callback.Invoke(rClazz);
    }
}

I want to reflect to invoke the methodExcute<T>(this GenericExcuteTestClass clazz, string parameter, Action<ReturnClass<T>> callback).

  1. I use thetypeof(GenericExcuteTestClassExtension).GetMethod("Excute", new Type[] { typeof(GenericExcuteTestClass), typeof(string), typeof(Action<ReturnClass<>>)}), but the compiler get the error "Type expected". How can I get type of (Action<ReturnClass<>>), Action<> can compliled, but it's not my expected.

  2. I want to pass the a custom action<ReturnClass<>> like (result)=>{....} to the method, how can I do it?

Please help ,thanks.

Why I use reflect to execute this ?

Because this method must execute in aop intercept

this real situation is like this:

I want to use restsharp in my app, and I write an interface like

 [RestfulService(Constants.BASE_URL + "/login")]
 public interface UserService
 {
    [Request("/login")]
    void Login([Paramter] string name, [Paramter] string password, Action<T> callBack);
 }

and Intercept the interface to get the parameter to execute restsharp ExecuteAsync<T>(this IRestClient client, IRestRequest request, Action<IRestResponse<T>> callback) to get data.

So I need to pass the T in UserService to ExecuteAsync<T> in Intercept method public void Intercept(IInvocation invocation) of castle.windsor, in this method body, we only can get GenericType's Type cannnot get T, so if I directly call ExecuteAsync, I cannot pass the GenericType T to this method. I must use like this:...GetMethod("...").MakeGenericType(new Type[]{piLast.ParameterType.GenericTypeArguments})

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
joinne
  • 43
  • 5
  • 2
    What do you expect `typeof(...).new Type[] { ... }` to do? What sort of statement are you expecting that to be? – Jon Skeet Oct 19 '13 at 08:23
  • Are you trying to do this using reflection, and if you are, then where are you getting the callback from? Why not just: clazz.Execute("some parameter", result => {...}); – Martin Ernst Oct 19 '13 at 08:25
  • sorry,it's `typeof(GenericExcuteTestClassExtension).GetMethod("Excute", new Type[] { typeof(GenericExcuteTestClass), typeof(string)` not` typeof(...)new Type[]` ,i Miss ".GetMethod("Excute", " – joinne Oct 19 '13 at 09:51
  • I do not understand the problem. You seem to be aware of the method `MakeGenericType`. Why can't you use that to construct any concrete generic type you want? Please elaborate. – usr Oct 19 '13 at 12:18
  • @MartinErnst i cannot call clazz.Execute,beacause the T is know when in run time. beside,i call this method in Intercept(IInvocation invocation) so i cannot pass the T from the parent.only i can get is Type of T. – joinne Oct 19 '13 at 16:11
  • possible duplicate of [Select Right Generic Method with Reflection](http://stackoverflow.com/questions/3631547/select-right-generic-method-with-reflection) – nawfal Jan 18 '14 at 05:55

1 Answers1

1

The whole problem comes from the fact, that nested generic types are not well handled by the reflection system in .NET.

The simplest solution in your case is to filter the methods yourself. A quick&dirty snippet:

MethodInfo method = null;

foreach (var m in typeof(GenericExcuteTestClassExtension)
                  .GetMethods(BindingFlags.Public | BindingFlags.Static))
{
    var parameters = m.GetParameters();

    if (!parameters.Any())
        continue;

    var lastParameterType = parameters.Last().ParameterType;
    var genericArgument = lastParameterType
        .GetGenericArguments()
        .SingleOrDefault();

    // you can/should add more checks, using the Name for example
    if (genericArgument != null && genericArgument.IsGenericType)
    {
        method = m;
        break;
    }
}

You should probably make an utility method from this. A general approach allowing to search for any method with nested generics can be found here. There is also another possibility using Expressions here.

Community
  • 1
  • 1
BartoszKP
  • 34,786
  • 15
  • 102
  • 130