2013-09-30 7 views
3

я следующий абстрактный класс и интерфейс:Заменить базовый класс с конкретной реализации C#

public interface ITypedEntity{ 
    TypedEntity Type { get; set; } 
} 

public abstract class TypedEntity:INamedEntity{ 
    public abstract int Id{get;set;} 
    public abstract string Name { get; set; } 
} 

Но когда я пытаюсь создать класс, который реализует ITypedEntity и имеет реализацию concrecte из TypedEntity я получаю следующее ошибка

Magazine does not implement interface member ITypedEntity.Type. Magazine.Type cannot implement 'ITypedEntity.Type' because it does not have the matching return type of 'TypedEntity' 

код для моей реализации concrecte ниже

public class Magazine:INamedEntity,ITypedEntity 
{ 
    public int Id {get;set;} 
    [MaxLength(250)] 
    public string Name {get;set;} 
    public MagazineType Type { get; set; } 
} 
public class MagazineType : TypedEntity 
{ 
    override public int Id { get; set; } 
    override public string Name { get; set; } 
} 

Я думаю, что понимаю, что происходит, но я не знаю, почему, потому что MagazineType - это TypedEntity.

Спасибо.

Update 1 Я должен отметить, что я хочу, чтобы использовать эти классы с EF CodeFirst и я хочу иметь другую таблицу для каждого из классов, реализующих ITypedEntity.

+0

MagazineType является TypedEntity но TypedEntity я sn't a MagazineType. Возможно, вы можете определить свой интерфейс как 'ITypedEntity Type {get; задавать; } ' –

+1

Но код, имеющий ссылку на журнал, хранящийся в переменной типа« ITypedEntity », может попытаться сохранить что-то, что * не является *' MagazineType', в свойство 'Type'. –

+0

изменить тип возврата 'Magazine.Type' на' EntityType'. Он все равно может быть экземпляром 'MagazineType', но подпись должна совпадать, чтобы насытить внедрение интерфейса. – Jodrell

ответ

7

Это не важно, что MagazineType является a TypedEntity. Представьте, что у вас есть другая реализация ITypedEntity, NewspaperType. Контракт интерфейса ITypedEntity утверждает, вы должны быть в состоянии сделать:

ITypedEntity magazine = new Magazine(); 
magazine.Type = new NewspaperType(); 

Однако это противоречит код, в котором Magazine.Type не принимает другие подтипы ITypedEntity. (Я считаю, что ваш код будет действительным, если имущество было только добытчик, хотя.)

Раствор будет использовать дженерики:

interface ITypedEntity<TType> where TType : TypedEntity 
{ 
    TType Type { get; set; } 
} 

class Magazine : ITypedEntity<MagazineType> 
{ 
    // ... 
} 
7

вам нужно изменить MagazineType к TypedEntity

public class Magazine:INamedEntity,ITypedEntity 
{ 
public int Id {get;set;} 
[MaxLength(250)] 
public string Name {get;set;} 
public TypedEntity Type { get; set; } 
} 

но при создании объекта журнала, то вы можете присвоить производный тип к нему

var magazine = new Magazine { Type = new MagazineType() } 
+0

Я знаю, что это работает, но проблема в том, что это некоторые модели, которые я намереваюсь использовать с EF CodeFirst, и я не уверен, как это будет работать, потому что я хочу иметь другую таблицу для каждого класса для правильной реализации TypedEntity – trebor

1

Для достижения этой цели вы должны добавить explicit implementation из ITypedEntity.Type:

public class Magazine:INamedEntity,ITypedEntity 
{ 
    public int Id {get;set;} 
    [MaxLength(250)] 
    public string Name {get;set;} 
    public MagazineType Type { get; set; } 

    TypedEntity ITypedEntity.Type 
    { 
     get 
     { 
      return this.Type; 
     } 
     set 
     { 
      this.Type = value as MagazineType; // or throw an exception if value 
               // is not a MagazineType 
     } 
    } 
} 

Использование:

Magazine mag = new Magazine(); 
mag.Type     \\ points to `public MagazineType Type { get; set; }` 
((ITypedEntity)mag).Type \\ point to `TypedEntity ITypedEntity.Type` 
Смежные вопросы