ссылка на желаемый перегруженный общий метод

Первое, на что нужно обратить внимание, это то, что аноним namespace не совпадает с namespace.

namespace
{
    bool operator==(const Foo&, const Foo&) {...}
}

- это действительно что-то вроде

namespace ANameUniqueToTheFile
{
    bool operator==(const Foo&, const Foo&) {...}
}

using ANameUniqueToTheFile;

с тем недостатком, что язык не дает вам возможности получить имя namespace.

По этой причине, функция operator==, определенная в анонимном namespace, не найдена с использованием ADL.


Я понимаю, почему вы хотите поместить функцию operator== в namespace. Один из возможных способов сделать это - файл #include .h, который определяет struct внутри именованного namespace.

FooWrapper.h:

namespace MyApp
{
   #include "foo.h"

   // Declare the function.
   bool operator==(Foo const& lhs, Foo const& rhs);
}

FooWrapper.cpp

#include "FooWrapper.h"

namespace MyApp
{
   // Implement the function.
   bool operator==(Foo const& lhs, Foo const& rhs) { ... }
}

Однако ...

Я понимаю, что немного упрощаю то, что в "foo.h". Добавление всех из них в namesapce MyApp может быть неуместным, особенно если «foo.h» включает в себя другие файлы .h и / или стандартные заголовочные файлы. Я надеюсь, что это даст вам некоторые идеи о том, как решить проблему.

Если поместить все «foo.h» в namespace MyApp не гладко, вероятно, будет целесообразно определить функцию operato== в глобальной области видимости.

13
задан John Saunders 6 February 2012 в 17:38
поделиться

4 ответа

Я не могу найти способ использовать GetMethod, который сделал бы то, что Вы хотите. Но можно получить все методы и пройти список, пока Вы не находите метод, который Вы хотите.

Помните, что необходимо назвать MakeGenericMethod, прежде чем можно будет на самом деле использовать его.

var allMethods = typeof (Example).GetMethods(BindingFlags.Public | BindingFlags.Static);
MethodInfo foundMi = allMethods.FirstOrDefault(
    mi => mi.Name == "Foo" && mi.GetGenericArguments().Count() == 2);
if (foundMi != null)
{
    MethodInfo closedMi = foundMi.MakeGenericMethod(new Type[] {typeof (int), typeof (string)});
    Example example= new Example();
    closedMi.Invoke(example, new object[] { 5 });
}
13
ответ дан 1 December 2019 в 23:48
поделиться

Вот острота Linq для того, в чем Вы нуждаетесь:

MethodInfo mi = exampleType.GetMethods().First(m=>m.GetGenericArguments().Length == 2);
0
ответ дан 1 December 2019 в 23:48
поделиться

Вот ответы на Ваши вопросы наряду с примером:

  1. Да, хотя существует две вещи действительно для знания здесь с общими методами, выводом типа и разрешением метода перегрузки. Вывод типа происходит во время компиляции, прежде чем компилятор пытается разрешить подписи перегруженного метода. Компилятор применяет логику вывода типа ко всем общим методам, которые совместно используют то же имя. На шаге разрешения перегрузки компилятор включает только те общие методы для который вывод типа, за которым следуют. Больше здесь...

  2. См. полный код программы Консольного приложения в качестве примера ниже этого шоу, как несколько вариантов метода Foo могут быть указаны в создании объекта MethodInfo и затем вызвали использование Дополнительного метода:

Program.cs

class Program
{
    static void Main(string[] args)
    {
        MethodInfo foo1 = typeof(Example).GetGenericMethod("Foo",
            new[] { typeof(string) },
            new[] { typeof(int) },
            typeof(void));

        MethodInfo foo2 = typeof(Example).GetGenericMethod("Foo",
            new[] { typeof(string), typeof(int) },
            new[] { typeof(int) },
            typeof(void));

        MethodInfo foo3 = typeof(Example).GetGenericMethod("Foo",
            new[] { typeof(string) },
            new[] { typeof(string) },
            typeof(void));

        MethodInfo foo4 = typeof(Example).GetGenericMethod("Foo",
            new[] { typeof(string), typeof(int) },
            new[] { typeof(int), typeof(string) },
            typeof(string));

        Console.WriteLine(foo1.Invoke(null, new object[] { 1 }));
        Console.WriteLine(foo2.Invoke(null, new object[] { 1 }));
        Console.WriteLine(foo3.Invoke(null, new object[] { "s" }));
        Console.WriteLine(foo4.Invoke(null, new object[] { 1, "s" }));
    }
}

Example.cs:

public class Example
{
    public static void Foo<T>(int ID) { }
    public static void Foo<T, U>(int ID) { }
    public static void Foo<T>(string ID) { }
    public static string Foo<T, U>(int intID, string ID) { return ID; }
}

Extensions.cs:

public static class Extensions
{
    public static MethodInfo GetGenericMethod(this Type t, string name, Type[] genericArgTypes, Type[] argTypes, Type returnType)
    {
        MethodInfo foo1 = (from m in t.GetMethods(BindingFlags.Public | BindingFlags.Static)
                           where m.Name == name &&
                           m.GetGenericArguments().Length == genericArgTypes.Length &&
                           m.GetParameters().Select(pi => pi.ParameterType).SequenceEqual(argTypes) &&
                           m.ReturnType == returnType
                           select m).Single().MakeGenericMethod(genericArgTypes);

        return foo1;
    }
}
3
ответ дан 1 December 2019 в 23:48
поделиться

I make a little modification of your lambda query.

When the parameter type si generic you must make that like that :

I add pi.ParameterType.GetGenericTypeDefinition()

and

(m.ReturnType.IsGenericType ? m.ReturnType.GetGenericTypeDefinition() : m.ReturnType) == returnType)

In this way the method working very fine

MethodInfo foo1 = (from m in t.GetMethods(BindingFlags.Public | BindingFlags.Static)
                         where m.Name == name
                         && m.GetGenericArguments().Length == genericArgTypes.Length
                         && m.GetParameters().Select(pi => pi.ParameterType.IsGenericType ? pi.ParameterType.GetGenericTypeDefinition() : pi.ParameterType).SequenceEqual(argTypes) &&
                         (returnType==null || (m.ReturnType.IsGenericType ? m.ReturnType.GetGenericTypeDefinition() : m.ReturnType) == returnType)
                         select m).FirstOrDefault();
      if (foo1 != null)
      {
        return foo1.MakeGenericMethod(genericArgTypes);
      }
      return null;

Example :

With the modification of the method i can call этот метод расширения

public static IQueryable<T> FilterCulture<T>(this Table<T> t, IDatabaseFilter filter)

С моим новым Помощником, подобным этому

var QueryableExpression = MethodInfoHelper.GetGenericMethod(typeof(LinqFilterExtension), "FilterCulture", new Type[] { rowType }, new Type[] { typeof(Table<>), typeof(IDatabaseFilter) }, typeof(IQueryable<>)); 

Подпись моего помощника:

   public static MethodInfo GetGenericMethod(Type t, string name, Type[] genericArgTypes, Type[] argTypes, Type returnType)
0
ответ дан 1 December 2019 в 23:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: