#c# #asp.net-mvc #asp.net-mvc-3 #interface #viewmodel
#c# #asp.net-mvc #asp.net-mvc-3 #интерфейс #viewmodel
Вопрос:
Я пытаюсь передать моему представлению экземпляр следующей ViewModel:
public class CompanyListViewModel<T> where T : ICompany
{
public IEnumerable<T> CompanyList;
public IEnumerable<string> StateList;
public CompanyListViewModel(IEnumerable<T> list)
{
CompanyList = list;
}
}
Где представление принимает что-то вроде этого:
@model Project.ViewModels.CompanyViewModels.CompanyListViewModel<ICompany>
И мой код контроллера передает что-то подобное представлению:
CompanyListViewModel<ICompanyInListAsUser> model = new CompanyListViewModel<ICompanyInListAsUser>(_companyService.FilterByCompanyState(state));
Где ICompanyInListAsUser
интерфейс реализует ICompany
интерфейс. _companyService.FilterByCompanyState(state))
Класс возвращает IEnumerable
несколько Company
объектов, которые, в свою очередь, реализуют ICompanyInListAsUser
интерфейс.
По какой-то причине я получаю следующую ошибку при доступе к моему представлению:
The model item passed into the dictionary is of type 'Project.ViewModels.CompanyViewModels.CompanyListViewModel`1[Project.ViewModels.CompanyViewModels.ICompanyInListAsUser]', but this dictionary requires a model item of type 'Project.ViewModels.CompanyViewModels.CompanyListViewModel`1[Project.ViewModels.CompanyViewModels.ICompany]'.
Почему я получаю эту ошибку, если ICompanyInListAsUser
интерфейс фактически реализует ICompany
?
Я был бы очень признателен за любую помощь.
Спасибо.
Редактировать
Я также хотел указать, чего я пытаюсь достичь здесь. Допустим, у меня есть несколько уровней доступа в моем приложении (например. Пользователь и администратор). Что, если у меня в Company
объекте есть свойство, доступное только администратору? Что ж, в таком случае моя ICompanyInListAsUser
модель включала бы все свойства, которые я хотел, в виде столбцов в списке, кроме свойства, доступного только администратору.
Итак, мой план здесь состоял в том, чтобы передать как ViewModel
интерфейс IEnumerable
базовой компании и из контроллера (или уровня обслуживания) выборочно заполнить IEnumerable
экземпляром одного из этих интерфейсов «фильтра», таких как ICompanyInListAsUser
.
Надеюсь, это имеет смысл, пожалуйста, дайте мне знать, если мне нужно уточнить.
Комментарии:
1. Вы не предоставляете достаточно информации. Что такое ICompanyInListAsUser?
2. Я думаю, что использование интерфейсов в моделях представления — это очень необычный шаблон. @gazarsgo, вероятно, прав, что вы должны использовать абстрактный базовый класс.
3. Чад, ICompanyInListAsUser — это просто интерфейс, содержащий свойства, которые я хочу отфильтровать из моего доменного объекта. Райан, не мог бы ты, пожалуйста, привести краткий пример того, где именно я бы использовал абстрактный базовый класс? Вы хотите сказать, создать абстрактный базовый класс, из которого происходят все мои интерфейсы «filter» и базовый объект Company? Отсюда сделайте мою ViewModel IEnumerable списком этого абстрактного базового класса? Спасибо!
Ответ №1:
То, чего вы пытаетесь достичь, должно быть возможно с помощью интерфейса для класса ViewModel и объявления универсального типа как ковариантного. Вот так:
interface ICompanyListViewModel<out T> where T : ICompany
{
}
Таким образом, вы также могли бы обойтись абстрактным классом вместо интерфейса для Company.
Ответ №2:
Подумайте о том, что интерфейсы не могут предоставлять реализации, когда вы думаете об этой ситуации, и должно стать очевидным, что вам нужно закрыть свой универсальный тип конкретным интерфейсом, с которым вы хотите, чтобы универсальный класс работал.
Если это не очевидно, что ж, рассмотрим далее, что с точки зрения чистой ООП интерфейсы не могут определять реализации, это могут только классы, и что C # не позволяет вам указывать перекрывающиеся интерфейсы.
Мне кажется, что вы пытаетесь рассматривать интерфейс как абстрактный базовый класс.
Комментарии:
1. Я понимаю, о чем вы говорите, просто мне трудно поместить это в контекст в этой ситуации.
2. так же просто, как изменить
CompanyListViewModel<ICompanyInListAsUser> model = new CompanyListViewModel<ICompanyInListAsUser>(_companyService.FilterByCompanyState(state));
наCompanyListViewModel<ICompany> model = new CompanyListViewModel<ICompany>(_companyService.FilterByCompanyState(state));