C#: Как получить правильный метод в обобщенном c классе с отражением в случае неоднозначного совпадения? - PullRequest
1 голос
/ 02 мая 2020

У меня есть следующий метод:

object Create(Type type)
{
    var constructor = type.GetConstructor(typeof(int));
    return constructor?.Invoke(new object[] {42});
}

Этот метод работает для большинства типов, либо находя конструктор и вызывая его, либо не возвращая ноль. Но, когда передается следующий тип, он выдает System.Reflection.AmbiguousMatchException:

class C<T>
{
    public C(int v) { Console.WriteLine("int"); }
    public C(T v) { Console.WriteLine("T"); }
}

Create(typeof(C<int>));

Это ожидается, так как есть два конструктора с одинаковой сигнатурой, но вопрос в следующем: как вызвать специфику c конструктор (в данном случае тот, который будет печатать "int")? Если я использую GetConstructors() и перечисляю их, я получаю два совершенно одинаковых конструктора. Похоже, что API ConstructorInfo и ParameterInfo не предоставляют никакой информации для различения guish их: оба являются не универсальными c методами, а типы параметров обоих являются Int32.

Тот же вопрос относится и к методам, отличным от конструкторов, которые следуют той же схеме.

1 Ответ

1 голос
/ 02 мая 2020

Один из возможных способов устранения неоднозначности конструкторов - посмотреть на свойство MetadataToken в ConstructorInfo:

// Get the ConstructorInfo for C<T>.C(int):
var c1 = typeof(C<>).GetConstructor(new[] { typeof(int) });

// Get the matching ConstructorInfo for C<int>.C(int):
var c2 = typeof(C<int>).GetConstructors().Single(c => c.MetadataToken == c1.MetadataToken);

c2.Invoke(new object[] { 42 }); // Outputs "int"

Я говорю «потенциал», потому что, хотя я получил желаемый результат при На моей машине, когда я тестировал код с. NET Core 2.0 и. NET Framework 4.7, я недостаточно знаком с. NET внутренними компонентами, чтобы понять, гарантированно ли работает этот подход.

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