Большое изображение:
Я нашел то, что кажется ограничением 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
.
Что я пробовал:
Я попробовал это в небезонной стране, чтобы узнать, правда ли это, что это такое. Мне пришлось использовать параметр шаблона в представлении, чтобы заставить его работать. Вот что выглядит не-бритва:
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.
EDIT:
На данный момент я просто добавляю вид бритвы для каждого подкласса BaseFooModel<BaseBarType>
. Я не волнуюсь об этом, потому что я не хочу создавать новое представление каждый раз, когда добавляю новую модель.
Другой вариант - просто воспользоваться тем фактом, что я могу заставить это работать в обычных классах С# без бритвы. Я мог бы просто просмотреть вид бритвы @inherits
С# view, а затем вызвать метод рендеринга. Мне не нравится этот параметр, потому что мне не нравится иметь два способа рендеринга 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
{
// ...
}