En resumen me gustaría ser capaz de pasar un modelo de vista genérico en mis vistasMVC modelo de vista genérico
Aquí hay un código simplificado de la esencia de lo que estoy tratando de lograr
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>());
}
}
Si yo crear mi punto de vista de la siguiente manera todos funciona como se espera
<%@ 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>
sin embargo, yo no quiero depender directamente de FakePerson en la vista en el caso de que quiero pasar alguna otra aplicación IPerson, por lo que tratado de cambiar la directiva de página a
<%@ Page Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<HomeViewModel<IPerson>>" %>
Pero claro que no funciona, por lo que, después de todo un día de curioseaba, tengo más canas y ni idea de qué hacer a continuación.
¿Alguien puede ayudar por favor?
[ACTUALIZACIÓN]
Algunos aconsejan ha sugested que debo utilizar una interfaz covariante; definir una interfaz no genérica y usarla en la Vista. Desafortunadamente lo he intentado pero hay una implicación adicional. Me gustaría que la función HtmlHelper para poder acceder a los atributos de anotación de datos que se pueden definir en la clase IPerson derivada
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;}
}
Así, mientras que el uso de una interfaz covariante esta manera funciona, en parte, para acceder al tipo derivado a través ViewModel; dado que la vista se escribe a la interfaz, parece que los atributos no son accesibles.
¿Existe alguna forma, en la vista, de acceder a estos atributos, tal vez con reflexión? ¿O podría haber otra forma de escribir la Vista en el genérico?
¿Cómo se puede esperar que su visión para el acceso deriva datos, pero no desea que dependa de los datos derivados? Puesto de otra forma, si accede a datos que son exclusivos de FakePerson, su vista depende de FakePerson, y como tal debería hacer que su modelo sea FakePerson. Si transfiere algún otro objeto, tendrá errores al acceder a FakePerson. –
No se pueden usar anotaciones de datos con interfaces de todos modos, ya que los atributos no se heredan (ver http://stackoverflow.com/questions/540749/can-ac-sharp-class-inherit-attributes-from-its-interface) –