Why can't my view model communicate with my generic ViewModel that implements the interface? (ASP.NET MVC 3)

I am trying to pass my View instance of the following ViewModel:

public class CompanyListViewModel<T> where T : ICompany { public IEnumerable<T> CompanyList; public IEnumerable<string> StateList; public CompanyListViewModel(IEnumerable<T> list) { CompanyList = list; } } 

If the view accepts something like this:

 @model Project.ViewModels.CompanyViewModels.CompanyListViewModel<ICompany> 

And my controller code passes something like this to the view:

 CompanyListViewModel<ICompanyInListAsUser> model = new CompanyListViewModel<ICompanyInListAsUser>(_companyService.FilterByCompanyState(state)); 

Where the ICompanyInListAsUser interface implements the ICompany interface. The _companyService.FilterByCompanyState(state)) class returns IEnumerable Company objects, which, in turn, implement the ICompanyInListAsUser interface.

For some reason, I get the following error while accessing my view:

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]'.

Why am I getting this error if the ICompanyInListAsUser interface really implements ICompany ?

Any help would be greatly appreciated.

Thanks.

EDIT

I also wanted to indicate what I am trying to achieve here. Let's say I have several access levels in my application (e.g. user and administrator). What if I have a property in my Company object, which is only an administrator? In this case, my ICompanyInListAsUser will include all the properties that I would like to use as columns in the list, except for the admin-only property.

So, my plan was to go through ViewModel a IEnumerable interface of the base company and selectively populate the IEnumerable instance of one of these "filtering" interfaces from the controller (or service level), for example ICompanyInListAsUser .

Hope this makes sense, please let me know if I need to clarify.

+6
source share
2 answers

What you are trying to accomplish should be possible through an interface for the ViewModel class and a Generic type declaration like Covariant. Like this:

 interface ICompanyListViewModel<out T> where T : ICompany { } 

That way, you can also get away with an abstract class instead of an interface for the company.

+6
source

Consider that interfaces cannot provide an implementation when you think about this situation, and it should become obvious that you need to close your generic type with the specific interface you want the generic class to work on.

If this is not obvious, then you should keep in mind that from the point of view of pure OOP, interfaces cannot define implementations, only classes can, and that C # does not allow you to specify overlapping interfaces.

It seems to me that you are trying to consider the interface as an abstract base class.

+1
source

Source: https://habr.com/ru/post/886518/


All Articles