大图:
我发现了 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。
编辑:
现在,我只是为BaseFooModel<BaseBarType>
. 我对此并不感到兴奋,因为我不想每次添加新模型时都必须创建新视图。
另一种选择是利用这样一个事实,即我能够在没有剃刀的情况下在常规 c# 类中使用它。我可以让我的剃刀查看@inherits
c# 视图,然后调用一些渲染方法。我不喜欢这个选项,因为我不喜欢有两种呈现 html 的方式。
还有其他想法吗?我知道当我用Foo
and给出类名时很难理解问题的上下文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
{
// ...
}