كيف يمكنني العثور على التحميل الزائد عام محدد باستخدام التفكير؟

StackOverflow https://stackoverflow.com/questions/1465715

سؤال

أنا أحاول إنشاء Expression من شأنها أن تستدعي طريقة محددة عامة محددة (Enumerable.Average في حالة الاختبار الأولى). لا تعرف ارتباطات النوع المحددة حتى وقت التشغيل، لذلك أحتاج إلى استخدام Reflection لإيجاد وإنشاء الطريقة العامة الصحيحة ( Expression يتم إنشاؤها من نص التحليل).

لذلك إذا كنت أعرف في وقت التشغيل الذي أريد العثور على هذا التحميل الزائد المحدد:

public static double Average<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector)

كيف يمكنني حل هذا بشكل خاص MethodInfo باستخدام الانعكاس؟

حتى الآن لدي بيان الاختيار التالي:

MethodInfo GetMethod(Type argType, Type returnType)
{
    var methods = from method in typeof(Enumerable).GetMethods(BindingFlags.Public | BindingFlags.Static)
      where method.Name == "Average" &&
      method.ContainsGenericParameters &&                              
      method.GetParameters().Length == 2 &&
      // and some condition where method.GetParameters()[1] is a Func that returns type argType
      method.ReturnType == returnType
      select method;

      Debug.Assert(methods.Count() == 1);
      return methods.FirstOrDefault();
}

ما سبق يضيقه إلى ثلاثة حمالات زائدة ولكن أريد أن أعكس وإيجاد التحميل الزائد المحدد الذي يأخذ Func<TSource, int> أين argType == typeof(int).

أنا جذري وأي مساعدة موضع تقدير.

هل كانت مفيدة؟

المحلول

تحتاج إلى استخدام methodInfo.makegenericmethod.

تحرير: حسنا، لقد أسيء فهم المشكلة ... يجب أن تفعل هذه الطريقة ما تريد:

MethodInfo GetMethod(Type argType, Type returnType)
{
    var enumerableType = typeof(IEnumerable<>).MakeGenericType(new Type[] { argType });
    Console.WriteLine(enumerableType);
    var methods = from method in typeof(Enumerable).GetMethods(BindingFlags.Public | BindingFlags.Static)
      let parameters = method.GetParameters()
      let genParams = method.GetGenericArguments()
      where method.Name == "Average" &&
      method.ContainsGenericParameters &&                              
      parameters.Length == 2 &&
      parameters[1].ParameterType.GetGenericTypeDefinition() == typeof(Func<,>) &&
      parameters[1].ParameterType.GetGenericArguments()[1] == argType &&
      method.ReturnType == returnType
      select method;

      return methods.FirstOrDefault();
}

نصائح أخرى

نظرا لأنك تقوم ببناء تعبير بدلا من التنفيذ مباشرة، فيمكنك تخطي الخطوة المنهة

var call = Expression.Call(typeof(Enumerable),
             "Average",
            new Type[] { typeof(MyTSource) },
            enumerableParameter, lambdaParameter
                );

هيريس كيفية القيام بذلك:

static MethodInfo GetMethod(Type argType, Type returnType)
{
    var methods = from m in typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
                  where m.ContainsGenericParameters
                  && m.Name == "Average"
                  && m.GetParameters()[1].ParameterType.GetGenericTypeDefinition() == typeof(Func<,>)
                  && m.GetParameters()[1].ParameterType.GetGenericArguments()[1] == returnType
                  select m;
    return methods.First();
}

شكرا joren للتلميح المرتبط. يميز هذا المثال بناء على الحجة، لكنه حصلت لي في الاتجاه الصحيح.

التحديد الذي يعمل هو

var methods = from method in typeof(Enumerable).GetMethods(BindingFlags.Public | BindingFlags.Static)
where method.Name == Name &&
method.ContainsGenericParameters &&                                                    
method.ReturnType == returnType &&
method.GetParameters().Length == 2 &&
method.GetParameters()[1].ParameterType.GetGenericArguments().Count() == 2 &&
method.GetParameters()[1].ParameterType.GetGenericArguments()[1] == argType
select method;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top