Вопрос по inheritance, c# – Как сделать правильное отражение базовых методов интерфейса

11

У меня есть 2 интерфейса и 2 класса, которые я исследую с помощью Reflection:

IParent IChild - derives from IParent Parent Child - derives from Parent

Для меня странным является тот факт, что когда я просматриваю отражение в типе IChild, я не нахожу метод IParent.

Тот же код, примененный к дочернему типу, работает как положено - отражение показывает метод Parent.

<code>interface IParent
{
     void ParentMethod();
}

interface IChild : IParent
{
     void ChildMethod();
}

class Parent 
{
     public void ParentMethod(){}
}

class Child : Parent
{
     public void ChildMethod(){}
}

void Main()
{
    //investigate derived interface
     Type t = typeof(IChild);
     var info = t.GetMethod("ChildMethod");//ok
     Console.WriteLine(info); 
     info = t.GetMethod("ParentMethod");//returns null!
     Console.WriteLine(info); 
     //investigate derived class
     t = typeof(Child);
     info = t.GetMethod("ChildMethod");//ok
     Console.WriteLine(info);
     info = t.GetMethod("ParentMethod");//ok
     Console.WriteLine(info);
}
</code>

Пожалуйста, объясните такое поведение?

Есть ли обходной путь, чтобы отразить методы базового интерфейса из типа производного интерфейса?

Parent не реализуетIParent...опечатка? Jamiec
Хороший вопрос. Я узнал кое-что, читая ответы. Не нужно было еще это знать, но знание - это сила ... Tony Hopkinson
@ Jamiec Нет, это не опечатка. Просто показывает различия в отражении унаследованных классов и интерфейсов. Konstantin Chernov

Ваш Ответ

3   ответа
10

Хотя мы используем интерфейсы так же, как мы используем наследование (& quot;: & quot;); интерфейсы не наследуются; они должны быть реализованы. В таком случае; Наследование путают с реализацией, так как они определены с использованием одного и того же оператора (& quot;: & quot;).

В качестве резюме; IA : IB а такжеA:IA средства; любой класс, реализующий IA, должен реализовывать IB. В этом случае; А должен реализовать IA и IB.

A:B означает, что класс наследует класс B; это не реализует.

Путаница здесь возникает из-за использования одного и того же оператора ("quot;").

Проверьте эту страницунаследование интерфейса

10

Если вы имеете дело с интерфейсом, используйте

t.GetInterfaces()

тогда вы можете проверить методы для типов, возвращенных выше.

Поиск членов интерфейса по имени не является надежным, имейте в виду, что, хотя в реализации интерфейса C # члены не могут быть переименованы при реализации, в CLR имена могут быть изменены. (IDisposable.Dispose () иногда переименовывается в Close). В иль есть инструкция под названием.implements что позволяет менять имена. Я считаю, что VB.Net также имеет эту функцию.

Error: User Rate Limit Exceeded Konstantin Chernov
5

base interfaces интерфейса (в этом случаеIParent является базовым интерфейсомIChild) являютсяexplicit base interfaces, Наследование - неудачное слово для интерфейсов, потому что классы, структуры и другие интерфейсы никогда неinherit из интерфейсов они просто реализуют контракт, который определяют базовые интерфейсы.

Когда вы выводитеIChild отIParent (обратите внимание, я не сказал наследовать), он не определяетParentMethod метод, он просто говоритanything that implements me, must also implement IParent.

Причина, по которой он работает, когда вы размышляете над реальным типом, заключается в том, что реализация интерфейса действительно определяет сигнатуры этого метода в самом типе, а это не относится к интерфейсам.

Это связано с процессом, который происходит компиляторомinterface mapping, который определяется как процесс поиска членов интерфейса в реализующем классе или структуре, но это не происходит для самого интерфейса.

Когда вы задумываетесь об интерфейсе, отображение интерфейса делаетnot происходят, поэтому отражается только сам интерфейс.

Type t = typeof(IChild);

Информация о типе будет содержать только информацию о типе явноIChild.

Type t = typeof(Child);

Здесь процесс отображения интерфейсаdoes происходят. Когда вы думаете о типеChild для метода с именемParentMethodкаждый базовый интерфейс проверяется до совпадения.

Это часть языкового дизайна. Подробнее об этом можно прочитать в разделе 13.1.4 языка программирования C # (четвертое издание) или в разделе 20.1.2 спецификации ECMA.

Вы можете обойти это несколько делаяinterface reimplementation, но это требует некоторого дополнительного кода.

interface IParent
{
    void ParentMethod();
}

interface IChild
{
    new void ParentMethod(); // Reimplement IParent.ParentMethod()
    void ChildMethod();
}

Это будет работать.

Type t = typeof(IChild);
MethodInfo mi = t.GetMethod("ParentMethod");

Из-за переопределения интерфейса,IChild теперь содержит сигнатуру методаParentMethod.

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