asp.net - 将通用模型的子类传递给 Razor View

标签 asp.net asp.net-mvc-3 oop razor

大图:

我发现了 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进入一个定义如下的 Razor View :
// FooView.cshtml
@model BaseFooModel<BaseBarType>

但是,这是行不通的。我收到一个运行时错误,说 FooView预计 BaseFooModel<BaseBarType>但得到 MyFooModel .回想一下 MyFooModel来自 BaseFooModel<MyBarType> 的遗产和 MyBarType继承自 BaseBarType .

我试过的:

我在非 Razor 的土地上尝试过这个,看看是否也是如此,它是。我必须在 View 中使用模板参数才能使其工作。这是非 Razor View :
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> 的每个子类添加一个 Razor View 。 .我对此并不感到兴奋,因为我不想每次添加新模型时都必须创建新 View 。

另一种选择是利用这样一个事实,即我能够在没有 Razor 的情况下在常规 c# 类中使用它。我可以有我的 Razor View @inherits c# 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
{
    // ...
}

最佳答案

您需要引入一个带有 covariant 的接口(interface)泛型类型参数到您的类层次结构中:

public interface IFooModel<out T> where T : BaseBarType
{
}

并从上述接口(interface)派生您的 BaseFooModel 。
public abstract class BaseFooModel<T> : IFooModel<T> where T : BaseBarType
{
}

在您的 Controller 中:
[HttpGet]
public ActionResult Index()
{
    return View(new MyFooModel());
}

最后,将 View 的模型参数更新为:
@model IFooModel<BaseBarType>

关于asp.net - 将通用模型的子类传递给 Razor View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15646812/

相关文章:

python - 奇怪的 Python OOP 函数调用错误

java - 当子类对象被指定为父类(super class)对象时会发生什么

asp.net - 升级到 ASP.NET 3.x

.net - 动态 ASP.net Web 窗体

asp.net - 从 App_Code 文件夹中的类访问 App_Data 中的文件

asp.net-mvc-3 - 在 Razor View 中仅显示日期

c# - 在 ASP.net MVC 3 中的按钮上应用 CSS

c# - 捕获 global.asax 中的特定错误

asp.net-mvc-3 - WIFI认证后User.Identity.Name为空

php - 如何获取创建当前对象的类?