使用viewmodels中的继承在MVC中提取视图

时间:2014-12-17 03:23:28

标签: c# asp.net-mvc inheritance

我需要一些关于如何在这种情况下继续进行的建议。假设我有一个视图,它呈现一个子部分视图和一个孙视图部分视图。一个部分视图称为_CommentsContainer,而另一个称为_Comment_CommentsContainer是遍历IPagedList<IComment>并为每个视图模型吐出_Comment的孩子。

/// <summary>
/// Represents an object that is able to hold comments or can be commented on. E.G. a photo, a video, a bulletin
/// , or even another comment
/// </summary>
public interface ICommentable
{
   IPagedList<IComment> Comments { get; set; }
}  


public interface IComment
{
    Guid Id { get; set; }
    string CommentingUsername { get; set; }
    Guid CommentingUserId { get; set; }
    DateTime? PostDate { get; set; }
    string Content { get; set; }

    Guid? InResposeToCommentId { get; set; }
}  

如果我想在我的_CommentsContainer中使用一个大的switch语句,我如何考虑继承此ICommentable但是实现它们自己的属性集的视图模型,这些属性不属于它继承的接口的一部分从?

@model Jdmxchange_V3.Models.Abstractions.Interfaces.ICommentable
@if (Model.GetType() == typeof(Jdmxchange_V3.Models.BulletinViewModels.BulletinDetailsViewModel))
{
<div class="row">
    <div class="panel panel-default recent-listings">
        <div class="panel-heading">Conversation</div>
        <div class="panel-body">
            @foreach (var comment in Model.Comments)
            {
                @Html.Partial("_Comment", comment)
            }
        </div>
    </div>
</div>
}

else if (Model.GetType() == typeof(Jdmxchange_V3.Models.EventDetailsViewModel))
{
<div class="row">
    <div class="panel panel-default recent-listings">
        <div class="panel-heading">Conversation @Model.EventSubTitle@*<< this property is not in ICommentable*@ </div>
        <div class="panel-body">
            @foreach (var comment in Model.Comments)
            {
                @Html.Partial("_Comment", comment)
            }
        </div>
    </div>
</div>
}  

如您所见,最后else if引用了ICommentable上找不到的属性。我可以简单地将此属性添加到ICommentable并使其成为所有派生类所必需的但是如果我不需要它在每个派生类上并且只需要在一个类上呢?我的问题是

在这种情况下,我如何在局部视图中提供某种类型的泛型类型,检查它的类型以及该特定类型的引用属性?

我最初的想法是,这是无法做到的,我从来没有看到它已经完成,也无法想到可以做到的类似情况。

2 个答案:

答案 0 :(得分:2)

我根本不会使用这种方法。相反,我会使用编辑器/显示模板,因为它们处理模型/属性的实际类型而不是@model语句中定义的内容。

例如,您可以在此处创建两个模板:

〜/查看/共享/ DisplayTemplates / BulletinDetailsViewModel.cshtml

@model BulletinViewModels.BulletinDetailsViewModel
<div class="row">
    <div class="panel panel-default recent-listings">
        <div class="panel-heading">Conversation</div>
        <div class="panel-body">
            @foreach (var comment in Model.Comments)
            {
                @Html.Partial("_Comment", comment)
            }
        </div>
    </div>
</div>

〜/查看/共享/ DisplayTemplates / EventDetailsViewModel.cshtml

@model BulletinViewModels.EventDetailsViewModel
<div class="row">
    <div class="panel panel-default recent-listings">
        <div class="panel-heading">Conversation @Model.EventSubTitle@</div>
        <div class="panel-body">
            @foreach (var comment in Model.Comments)
            {
                @Html.Partial("_Comment", comment)
            }
        </div>
    </div>
</div>

然后你就在主视图中了:

@model Jdmxchange_V3.Models.Abstractions.Interfaces.ICommentable

@Html.DisplayForModel()

或者您可以使用

@Html.DisplayFor(m => m)

您还可以使用编辑器模板而不是部分模板来评论。 EditorTemplates会自动遍历IEnumerables,所以你只需要这样做:

@Html.DisplayFor(m => m.Comments)

答案 1 :(得分:1)

不幸的是,类型没有switch语句。你最好的选择是比较像你一样的类型,尽管通过is比较可以更容易理解,并利用多态性,如下所示:

@using Jdmxchange_V3.Models
@if (Model is BulletinViewModels.BulletinDetailsViewModel)
{
    var bdvm = Model as BulletinViewModels.BulletinDetailsViewModel;
    // do things specific to this type
}
else if(Model is EventDetailsViewModel)
{
    var edvm = Model as EventDetailsViewModel;
    // do things specific to this type
}

你没有要求这一点,但无论如何我都会把它放在这里:我建议你可能不需要孙子部分。您可以通过消除孙子视图并使_CommentsContainer部分视图呈现所有内容来节省一些分配(和垃圾收集加载)。如果您的网站没有很多用户或长评论帖,那么性能可能并不重要,您应该继续保持原样。