MVC通用ViewModel

ric*_*rdo 8 asp.net generics asp.net-mvc viewmodel

总之,我希望能够将通用的ViewModel传递给我的视图

以下是我想要实现的目标的一些简化代码

public interface IPerson
{
    string FirstName {get;}
    string LastName {get;}
}

public class FakePerson : IPerson
{
    public FakePerson()
    {
        FirstName = "Foo";
        LastName = "Bar";
    }

    public string FirstName {get; private set;} 
    public string LastName {get; private set;} 
}

public class HomeViewModel<T> 
    where T : IPerson, new()
{
    public string SomeOtherProperty{ get; set;}
    public T Person { get; private set; }

    public HomeViewModel()
    {
        Person = new T();
    }
}

public class HomeController : Controller {
    public ViewResult Index() {
        return View(new HomeViewModel<FakePerson>());
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我按如下方式创建我的视图,则按预期工作

<%@ Page Language="C#" 
    MasterPageFile="~/Views/Shared/Site.Master"
    Inherits="System.Web.Mvc.ViewPage<HomeViewModel<FakePerson>>" %>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <%: Html.DisplayFor(m=>m.Person.FirstName) %>
    <%: Html.DisplayFor(m=>m.Person.LastName) %>   
</asp:Content>
Run Code Online (Sandbox Code Playgroud)

但是,如果我想传递其他一些IPerson实现,我不希望在视图中直接依赖FakePerson,所以我尝试将页面指令更改为

<%@ Page Language="C#" 
    MasterPageFile="~/Views/Shared/Site.Master"
    Inherits="System.Web.Mvc.ViewPage<HomeViewModel<IPerson>>" %>
Run Code Online (Sandbox Code Playgroud)

但当然这不起作用,所以,经过一整天的磨砺,我有更多的白发,不知道接下来该做什么.

请有人帮忙吗.

[UPDATE]

有人建议我应该使用协变接口; 定义非泛型接口并在View中使用它.不幸的是,我尝试了这一点,但有一个附带的含义.我希望HtmlHelper函数能够访问可能在IPerson派生类中定义的任何数据注释属性

 public class FakePerson : IPerson
 {
    public FakePerson()
    {
        FirstName = "Foo";
        LastName = "Bar";
    }

    [DisplayName("First Name")]
    public string FirstName {get; private set;}

    [DisplayName("Last Name")]
    public string LastName {get; private set;} 
}
Run Code Online (Sandbox Code Playgroud)

因此,在使用协变接口时,这种方式可以部分地通过ViewModel访问派生类型.由于视图是在界面上键入的,因此无法访问属性.

在视图中,是否有一种方法可以通过反射访问这些属性.或者可以在其他方面键入View到泛型.

SLa*_*aks 0

你的代码几乎是正确的;你只需要在控制器中传递一个HomeViewModel<IPerson>(不是)。FakePerson

您还可以在视图中使用模型的协变接口,但这可能有点过头了。