Передать подкласс общей модели в вид бритвы
Большая картинка:
Я нашел то, что кажется ограничением Razor, и у меня возникли проблемы с поиском хорошего способа обойти это.
Игроки:
Допустим, у меня есть такая модель:
public abstract class BaseFooModel<T>
where T : BaseBarType
{
public abstract string Title { get; } // ACCESSED BY VIEW
public abstract Table<T> BuildTable();
protected Table<T> _Table;
public Table<T> Table // ACCESSED BY VIEW
{
get
{
if (_Table == null)
{
_Table = BuildTable();
}
return _Table;
}
}
}
И такой подкласс:
public class MyFooModel : BaseFooModel<MyBarType>
{
// ...
}
public class MyBarType : BaseBarType
{
// ...
}
Я хочу быть в состоянии пройтиMyFooModel
в бритву, которая определяется следующим образом:
// FooView.cshtml
@model BaseFooModel<BaseBarType>
Но это не работает. Я получаю ошибку во время выполнения, говоря, чтоFooView
ожидаетBaseFooModel<BaseBarType>
но получаетMyFooModel
, Напомним, чтоMyFooModel
в наследство отBaseFooModel<MyBarType>
а такжеMyBarType
наследует отBaseBarType
.
Что я пробовал:
Я попробовал это на не бритвой земле, чтобы увидеть, правда ли то же самое, что и есть. Мне пришлось использовать шаблон param в представлении, чтобы заставить его работать. Вот это не бритвенное представление:
public class FooView<T>
where T : BaseBarType
{
BaseFooModel<T> Model;
public FooView(BaseFooModel<T> model)
{
Model = model;
}
}
С этой структурой, следующееработает:
new FooView<MyBarType>(new MyFooModel());
Мой вопрос:
Как я могу сделать это с Razor? Как я могу передать тип, как я делаю сFooView
?
Я не могу, но есть ли способ обойти это? Можно ли как-то добиться такой же архитектуры?
Дайте мне знать, если я могу предоставить больше информации. Я использую .NET 4 и MVC 3.
РЕДАКТИРОВАТЬ:
Сейчас я просто добавляю бритву для каждого подклассаBaseFooModel<BaseBarType>
, Меня это не волнует, потому что я не хочу создавать новый вид каждый раз, когда добавляю новую модель.
Другой вариант - просто воспользоваться тем, что яя в состоянии получить это работает в обычных классах C # без бритвы. Я мог бы просто иметь мой взгляд бритвы@inherits
представление c # и затем вызовите некоторый метод рендеринга. Мне не нравится этот вариант, потому что мне не нравятся два способа рендеринга html.
Есть еще идеи? Я знаю, что трудно понять контекст проблемы, когда я даю имена классов сFoo
а такжеBar
, но я не могу предоставить слишком много информации, так как она немного чувствительна. Мои извинения за это.
Что у меня есть, используя ответ Бенджамина:
public interface IFooModel<out T>
where T : BaseBarModel
{
string Title { get; }
Table<T> Table { get; } // this causes an error:
// Invalid variance: The type parameter 'T' must be
// invariantly valid on IFooModel<T>.Table.
// 'T' is covariant.
}
public abstract class BaseFooModel<T> : IFooModel<T>
where T : BaseBarModel
{
// ...
}
Что в итоге получилось:
public interface IFooModel<out T>
where T : BaseBarModel
{
string Title { get; }
BaseModule Table { get; } // Table<T> inherits from BaseModule
// And I only need methods from BaseModule
// in my view.
}
public abstract class BaseFooModel<T> : IFooModel<T>
where T : BaseBarModel
{
// ...
}