2017-02-03 16 views
1

Мне нужно написать класс под названием Vehicle со многими атрибутами (например, размер, места, цвет, ...), а также у меня есть еще два класса для написания: Trunk и Car со своими атрибутами.Интерфейс с абстрактным классом

Так что я написал:

// Vehicle.cs 
abstract public class Vehicle 
{ 
    public string Key { get; set; } 
    ... 
} 

// Car.cs 
public class Car : Vehicle 
{ 
    ... 
} 

// Trunk.cs 
public class Trunk : Vehicle 
{ 
    ... 
} 

После этого я написал интерфейс:

// IVehicleRepository.cs 
public interface IVehicleRepository 
{ 
    void Add(Vehicle item); 
    IEnumerable<Vehicle> GetAll(); 
    Vehicle Find(string key); 
    Vehicle Remove(string key); 
    void Update(Vehicle item); 
} 

Так я думал, что я мог бы использовать что-то вроде этого:

// CarRepository.cs 
public class CarRepository : IVehicleRepository 
{ 
    private static ConcurrentDictionary<string, Car> _cars = 
      new ConcurrentDictionary<string, Car>(); 

    public CarRepository() 
    { 
     Add(new Car { seats = 5 }); 
    } 

    public IEnumerable<Car> GetAll() 
    { 
     return _cars.Values; 
    } 

    // ... I implemented the other methods here 

} 

Но у меня были ошибки:

ошибка CS0738: «CarRepository» не реализует элемент интерфейса «IVehicleRepository.GetAll()». 'CarRepository.GetAll()' не может реализовать 'IVehicleRepository.GetAll()', потому что у него нет соответствующего типа возврата 'IEnumerable <' Vehicle> '.

Итак, как я могу это сделать?

ответ

7

Ваш CarRepository не реализует метод. Эти два не то же самое:

  • public IEnumerable<Car> GetAll()
  • IEnumerable<Vehicle> GetAll()

Это два разных типа, и когда вы черпаете из интерфейса вы должны реализовать это точно. Вы можете просто реализовать это следующим образом:

public IEnumerable<Vehicle> GetAll() 
{ 
    // Cast your car collection into a collection of vehicles 
} 

Однако лучше всего было бы сделать общий интерфейс: (Недостатком является то, что два различных реализаций типа снова два типа так увидеть, если это то, что вы хотите)

public interface IVehicleRepository<TVehicle> {} 
public class CarRepository : IVehicleRepository<Car> {} 

более полная версия:

public interface IVehicleRepository<TVehicle> where TVehicle : Vehicle 
{ 
    void Add(TVehicle item); 
    IEnumerable<TVehicle> GetAll(); 
    Vehicle Find(string key); 
    Vehicle Remove(string key); 
    void Update(TVehicle item); 
} 

public class CarRepository : IVehicleRepository<Car> 
{ 
    private static ConcurrentDictionary<string, Car> _cars = 
      new ConcurrentDictionary<string, Car>(); 

    public CarRepository() 
    { 
     Add(new Car { seats = 5 }); 
    } 

    public IEnumerable<Car> GetAll() 
    { 
     return _cars.Values; 
    } 
} 
+0

Спасибо, ребята (http://stackoverflow.com/users/6400526/gilad-green и http://stackoverflow.com/users/5528593/ren%C3%A9-vogt). Это помогло мне, но у меня другая проблема. Если у меня есть только один репозиторий, я могу ввести его в «public void ConfigureServices (службы IServiceCollection)» на Startup.cs: services.AddSingleton (); Но теперь у меня есть два репозитория: CarRepository и TrunkRepository (расширение IVehicleRepository). Как я могу сейчас вводить CarRepository и TrunkRepository? – shibata

+0

@ Олаво Шибате - рад, что это помогло. Если это помогло вам решить конкретную проблему, пожалуйста, подумайте о том, чтобы разметка была решена. Что касается другого вопроса - политика заключается в том, что последующие вопросы должны быть опубликованы в отдельном вопросе. Пожалуйста, найдите похожие проблемы, которые у вас есть, и вам нужна помощь, пожалуйста, напишите новый вопрос, и мы будем рады помочь. –

+0

Конечно, спасибо. – shibata

1

вы могли бы сделать IVehicleRepository родовое:

public interface IVehicleRepository<T> where T : Vehicle 
{ 
    void Add(T item); 
    IEnumerable<T> GetAll(); 
    Vehicle Find(string key); 
    Vehicle Remove(string key); 
    void Update(T item); 
} 

, а затем реализовать классы, как это:

public class CarRepository : IVehicleRepository<Car> 
{ 
    private static ConcurrentDictionary<string, Car> _cars = 
      new ConcurrentDictionary<string, Car>(); 

    public CarRepository() 
    { 
     Add(new Car { seats = 5 }); 
    } 

    public IEnumerable<Car> GetAll() 
    { 
     return _cars.Values; 
    } 
} 

Но вы тогда все еще есть проблема, что CarRepository является IVehicleRepository<Car> в то время как TruckRepository будет IVehicleRepository<Truck>. И эти два интерфейса: разные типы и назначаются друг другу только в том случае, если у них есть правильный variance.