2012-05-02 1 views
2

Я оказался в ситуации, когда у меня есть метод в базовом классе, который вызывает вызов общего метода, передающего себя как параметр (через this). В универсальном методе тип всегда является базовым типом, даже когда я вызываю метод из производного класса.typeof это в виртуальных методах, вызванных из производного класса

Мне нужен общий метод, чтобы знать, что он имеет производный тип, а не базовый тип.

Я не могу изменить общий метод, так как это от стороннего приложения (http://razorengine.codeplex.com/ - Razor.Parse).

Я обнаружил, что если я определяю метод как общий метод расширения, ограниченный типами, наследуемыми от моего базового класса, который вызывает это, то работает, но кажется бесполезным использовать методы расширения для этой цели (хотя, если это верно использование I будем рады услышать это). Я задаюсь вопросом, есть ли какой-нибудь трюк, который я могу использовать, который преобразует «это» в тип производного объекта до его вызова (возможно, с использованием дженериков все еще).

Я включил упрощенную программу ниже, которая должна быть автономной (я запускаю ее в LINQPad для личной непринужденности). По сути, я хочу, чтобы метод, определенный на A, при вызове экземпляра B вызывал Test.WhatType и выводил «B».

Надеюсь, это имеет смысл.

void Main() 
{ 
    var bar = new B(); 
    bar.myGetType(); 
    bar.ExtGetType(); 
} 

class A 
{ 
    public virtual void myGetType() 
    { 
     Test.WhatType(this); 
     this.ExtGetType(); 
    } 
} 

class B : A {} 

static class ext 
{ 
    public static void ExtGetType<T>(this T obj) where T : A 
    { 
     Test.WhatType(obj); 
    } 
} 

class Test 
{ 
    public static void WhatType<T>(T obj) 
    { 
     Console.WriteLine(typeof(T).Name); 
    } 
} 

Edit: Измененное имя метода A.myGetType(), так как я даже не заметил, что я перегружать случайно.

N.B. Выполнение этих выходов кода:

A 
A 
B 
+0

Если шаблонный метод заботится о типе, мимо ', где T: A', то вы необходимо переоценить этот метод. – cadrell0

+0

Ну, это правда - вызывающий код IS class A! (Я знаю, что это не полезно) У меня будет копать и попробуйте вернуться к вам! –

+0

Вам нужно будет использовать obj.GetType() вместо метода WhatType. –

ответ

2

Если я правильно понял, ваша проблема в том, что A.GetType() является обязательным для WhatType<A>, поскольку это все, что он знает.

Значит, класс A знает о производных классах.

Вы можете сделать это с помощью саморегуляции общих типов.Что-то вроде:

class A<T> where T : A<T> 
{ 
    public virtual void GetType() 
    { 
     Test.WhatType<T>((T) this); 
    } 
} 

class B : A<B> { } 

затем:

new B().GetType(); 

будет связываться с WhatType<B> и так будет выводить B

+0

А, это было то, о чем мне было интересно. Я не уверен, что теперь я рассматриваю это как решение, будь то какой-нибудь аккуратный, но спасибо за то, что вы поделились. Это, конечно, похоже, что это будет полезно в целом. :) – Chris

+0

Вызов метода расширения из 'A.GetType()' выдает 'A' - я думал, что вы хотите, чтобы он выводил' B'? –

+0

Я не уверен, что понимаю ваш последующий вопрос. – Chris

-1

Этот метод возвращает тип статического типа (T). Она должна быть реализована в виде

public static void WhatType<T>(T obj) 
{ 
    Console.WriteLine(obj.GetType().Name); 
} 

Edit: Я просто понял, что вы хотите, чтобы манипулировать таким образом, что Т из общих изменений методы. Вы можете сделать это с помощью рефлексии или путем добавления оператора switch на основе подтипа A и явно передать это B (или любому классу). Конечно, ни одно из этих решений не является хорошим, потому что A будет зависеть от своих подклассов и отражения явно sux. Другой вариант - переопределить метод GetType() в каждом подклассе и, таким образом, перенести ответственность на подклассы.

+1

typeof требует типа. Я думаю, вы имеете в виду obj.GetType() – cadrell0

+1

Это никогда не будет компилироваться. 'obj' не является допустимым параметром' typeof'. Он ожидает имя типа. – jason

+0

Вы правы. Исправлена. – Stilgar

3

Вам необходимо использовать obj.GetType(). T привязан во время компиляции, а не во время выполнения, и поэтому typeof(T) возвращает тип времени компиляции T.

+0

Ах. Да, поэтому мое тестирование было неправильным. 'Test.WhatType' должен был быть симуляцией статического метода в стороннем приложении, который, кажется, рассматривает переданный параметр как базовый класс. Похоже, моя проблема может быть на самом деле с библиотекой RazorEngine. Я пойду посмотрю. Спасибо за помощь. :) – Chris

+0

И действительно, я обнаружил, что метод 'Razor.Parse', который я вызывал, действительно, кажется, использует' typeof (T) 'внутренне, а не' mode.GetType() '. Наверное, я буду жаловаться на них. ;-) – Chris

Смежные вопросы