Если у меня есть MethodInfo для закрытого универсального типа, есть ли простой способ переключения этих типов? - PullRequest
8 голосов
/ 05 ноября 2010

Допустим, у меня есть methodInfo для чего-то вроде Nullable<int>.HasValue. Есть ли способ конвертировать его в Nullable<string>.HasValue?

Я знаю, что для обычного универсального метода я могу сделать methodInfo.GetGenericMethod(), но я не вижу способа сделать это для типа из метода, без дополнительных затрат на отражение. Если у меня уже есть метод, почему я должен снова задуматься?

Интересно, что все методы имеют одинаковый MetadataToken, что делает более впечатляющим то, что каким-то образом Module.ResolveMember, похоже, вытягивает правильный.

Есть ли способ сделать это с Module.ResolveMethod? По сути, метод и тип могут иметь общие параметры, и мне может потребоваться их переключить. Так как MethodInfo всегда говорит, что его токен один и тот же, а токен представляет собой MethodInfo - самая открытая версия метода. Мне просто нужно как-то преобразовать его в мой тип.

Edit: Более подробно, кажется, что для чего-то вроде List<T>.Add, List<int>.Add токен метаданных, из которого я получаю, фактически живет в моем модуле, в то время как общее определение находится в другом модуле.

Я действительно не хочу делать рефлексию, когда получаю член один раз, так как очень трудно разрешить тот же самый вызываемый метод.

Ладно, может быть, я просто глуп, но почему именно это не работает ::

var methodinfo = typeof(List<int>).GetMethod("Add");
var handle = methodinfo.MetaDataToken;
var methodinfo2 = methodinfo.Module.ResolveMethod(handle,new []{typeof(string)},null);

Почему methodInfo2 говорит, что это Add(T), а не Add(string)?

Ответы [ 4 ]

10 голосов
/ 05 ноября 2010

Вы можете сделать это в одной строке с MethodBase.GetMethodFromHandle, но чтобы использовать этот метод, вам нужно передать typeof(List<string>), а не просто typeof(string).

var methodinfo = typeof(List<int>).GetMethod("Add");
var methodinfo2 = MethodBase.GetMethodFromHandle(methodinfo.MethodHandle,
                                                 typeof (List<string>).TypeHandle);

Console.WriteLine(methodinfo);
Console.WriteLine(methodinfo2);

Эта ссылка включает в себя приведенный выше пример и объяснение того, почему ResolveMethod не работает.

https://www.re -motion.org / блог / микс / архив / 2009/08/12 / пытаюсь к решимости-а-метод-в-замкнутого-родовому-type.aspx

2 голосов
/ 05 ноября 2010

Вы можете сделать это легко, немного больше размышлений.Вы не можете сделать это волшебным образом без отражения.

    static void Main(string[] args)
    {
        PropertyInfo intHasValue = typeof (int?).GetProperty("HasValue");
        PropertyInfo boolHasValue = ChangeGenericType(intHasValue, typeof (bool));
    }

    public static PropertyInfo ChangeGenericType(PropertyInfo property, Type targetType)
    {
        Type constructed = property.DeclaringType;
        Type generic = constructed.GetGenericTypeDefinition();
        Type targetConstructed = generic.MakeGenericType(new[] {targetType});
        return targetConstructed.GetProperty(property.Name);
    }

Конечно, это довольно специфично для работы только с универсальными типами с одним параметром типа, но его можно обобщить, чтобы сделать больше при необходимости.

0 голосов
/ 05 ноября 2010

Решил это. Но большой вопрос, это безопасный способ сделать это? Есть ли что-то, что я мог бы сделать здесь неправильно?

    public static MethodInfo Convert(this MethodInfo method,params Type[] DeclaringTypeArguments)
    {
        var baseType = method.DeclaringType.GetGenericTypeDefinition().MakeGenericType(DeclaringTypeArguments);
        return MethodInfo.GetMethodFromHandle(method.MethodHandle, baseType.TypeHandle) as MethodInfo;
    }
    public static void Main(String[] args)
    {
        List<Type> list = new List<Type>(); 
        Action<Type> action  = list.Add;
        Console.WriteLine(action.Method.Convert(typeof(string)));
        Console.Read();
    }
0 голосов
/ 05 ноября 2010

Вы должны снова задуматься, потому что методы разные.Хотя единственное отличие для HasValue - это MethodInfo.DeclaringType, различие в свойстве Value - это MethodInfo.ReturnType.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...