2013-08-30 2 views
8

Мне нужно вызвать метод абстрактной реализации класса. Но компилятор всегда по умолчанию использует перегруженный метод из конкретного класса, так как для подписи требуется только унаследованный тип.Метод вызова, перегруженный из абстрактного класса

Просто взгляните на код:

- это, очевидно, значительно упрощенная версия фактического кода, который я использую;)

public class ModelBase { } 
public class ModelA : ModelBase { } 
public interface IInterface<in TModel> 
{ 
    void Do(TModel model); 
} 
public abstract class AbstractClass<TModel> : IInterface<TModel> 
{ 
    public abstract void Do(TModel model); 
} 
public class ConcreteClass : AbstractClass<ModelA>, IInterface<ModelBase> 
{ 
    public override void Do(ModelA model) 
    { 
     // I'd like to invoke this method 
    } 

    public void Do(ModelBase model) 
    { 
     // how do I invoke the method above?? 
     Do((ModelA)model); 
    } 
} 

^^ Это приводит к рекурсии

То, что я попытался это:

((IClass<ModelA>)this).Do((ModelA)model); 

^^ ничего не меняет

base.Do((ModelA)model); 

^^ выдает ошибку "не удается вызвать абстрактный элемент базы: 'AbstractClass.Do (Modela)"

Как я называю "общественное переопределение недействительной (модель Modela) Do" метод ?


кстати. Если изменить класс этого

public class ConcreteClass : IInterface<ModelA>, IInterface<ModelBase> 

это работает.

+0

Это выглядит как ошибка компилятора перегрузки распознаватель ... Что я упускаю –

+0

Если я могу, почему у вас есть перегрузки который использует базовый тип, но затем делает вызов, предполагая, что тип является ModelA? Способ настройки перегрузки, я мог бы дать вам ModelB. –

+0

Очень действительный вопрос @neoistheone. В основном у меня есть IRepository , который запрашивается. A Бетонный репозиторий . Теперь метод Insert вызывается в интерфейсе репозитория. Хотя это контравариантно, я не могу отдать IRepository в IRepository . поэтому я должен добавить наследование IRepository в конкретный репозиторий. – Sam7

ответ

9

В ролях this к AbstractClass<ModelA> перед вызовом:

public void Do(ModelBase model) 
{ 
    ((AbstractClass<ModelA>)this).Do((ModelA)model); 
} 
+1

Да, собирался опубликовать то же самое. Вот хороший пост для понимания решения метода экземпляра базы vs: http://stackoverflow.com/questions/12110565/why-overloaded-methods-have-lower-priority-than-instance-method – DavidN

+0

Спасибо! Я был так близок с '((IClass ) this) .Do ((модель Model)); :) – Sam7

4

Использовать именованные параметры:

public class ConcreteClass : AbstractClass<ModelA>, IInterface<ModelBase> 
{ 
    public override void Do(ModelA modelA) // change 'model' into 'modelA' 
    { 
     // I'd like to invoke this method 
    } 

    public void Do(ModelBase model) 
    { 
     // how do I invoke the method above?? 
     Do(modelA : (ModelA)model); 
    } 
} 

Теперь компилятор знает, что вы хотите вызвать метод Do(ModelA), а не метод Do(ModelBase).

+3

+1 Это роман, если он опасен. –

+0

Да, это опасно, но это работает :-) – ProgramFOX

+1

Хорошее мышление! :) – Sam7

3

Try реализовать интерфейс в явном виде. Теперь вы можете вызвать метод IInterface<ModelBase>.Do(ModelBase model) только ссылки типа IInterface<ModelBase>

public class ModelBase { } 
public class ModelA : ModelBase { } 
public interface IInterface<in TModel> 
{ 
    void Do(TModel model); 
} 
public abstract class AbstractClass<TModel> : IInterface<TModel> 
{ 
    public abstract void Do(TModel model); 
} 
public class ConcreteClass : AbstractClass<ModelA>, IInterface<ModelBase> 
{ 
    public override void Do(ModelA model) 
    { 
     Console.Write("Do - Override AbstractClass<ModelA> "); 
    } 

    void IInterface<ModelBase>.Do(ModelBase model) 
    { 
     Console.Write("Do - IInterface<ModelBase> "); 
     Do(model as ModelA); 
    } 
} 

void Main() 
{ 
    var modelA = new ModelA(); 

    (new ConcreteClass() as IInterface<ModelBase>).Do(modelA); //output -> Do - IInterface<ModelBase> Do - Override AbstractClass<ModelA> 
    Console.WriteLine(); 
    new ConcreteClass().Do(modelA); //output -> Do - Override AbstractClass<ModelA> 
} 
+0

Спасибо. Я мог бы пойти с этим решением. :) – Sam7

+0

Кстати, обратите внимание на это Do (модель как ModelA); потому что вы не можете быть уверены, что переменная модель является экземпляром ModelA или одного из его подклассов –

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