2011-02-11 21 views
28

¿Podría alguien aclarar algo para mí? En mi aplicación ASP.NET MVC 2, tengo una clase BaseViewModel que incluye el siguiente método:Los argumentos de tipo no se pueden deducir del uso. Intente especificar los argumentos de tipo explícitamente

public virtual IDictionary<string, object> GetHtmlAttributes<TModel, TProperty> 
         (Expression<Func<TModel, TProperty>> propertyExpression) 
{ 
    return new Dictionary<string, object>(); 
} 

La idea es que cada modelo de vista niño puede reemplazar este método y proporcionar un conjunto adecuado de atributos HTML, basado en cierta lógica, que se representan en la vista:

<%: Html.TextBoxFor(model => model.MyProperty, Model.GetHtmlAttributes 
               (model => model.MyProperty)) %> 

Sin embargo, cuando se usa como en la línea de arriba, me sale un error de compilación cuando llegué a la vista:

los argumentos de tipo conocido para hod '...BaseViewModel.GetHtmlAttributes<TModel,TProperty> Expression<System.Func<TModel,TProperty>)' no se puede deducir del uso. Intente especificar los argumentos de tipo explícitamente.

tengo que hacer lo siguiente:

<%: Html.TextBoxFor(model => model.MyProperty, Model.GetHtmlAttributes 
          <ChildModel, string>(model => model.MyProperty)) %> 

sólo estoy buscando un poco de claridad en cuanto a la forma en que trata de inferir el tipo, se ha de hacer por lo que no hay problema en el método HtmlHelper/TextBoxFor extensión?

¿Es porque HtmlHelper en la vista serán automáticamente por el mismo tipo que se especifica en el ViewUserControl en la parte superior de la página, mientras que el código puede ser de cualquier tipo que hereda de BaseViewModel? ¿Es posible escribir esto de tal manera que pueda inferir mis modelos/tipos de propiedad?

+5

Holy horizontal scrollbars batman! –

+2

Sí totalmente. Es absurdo que en nuestros monitores de 30 "obtengamos solo 6.5" para desplazar el código hacia adelante y hacia atrás en estas pequeñas ventanas. ¡Vamos, muchachos, tomen su dinero de VC y obtengan el tamaño dinámico de la página! – Slaggg

Respuesta

11

En su ejemplo, el compilador no tiene manera de saber qué tipo debe ser TModel. Podría hacer algo parecido a lo que probablemente esté tratando de hacer con un método de extensión.

static class ModelExtensions 
{ 
    public static IDictionary<string, object> GetHtmlAttributes<TModel, TProperty> 
     (this TModel model, Expression<Func<TModel, TProperty>> propertyExpression) 
    { 
     return new Dictionary<string, object>(); 
    } 
} 

Pero no sería capaz de tener algo similar a virtual, creo.

EDIT:

En realidad, se puede hacer virtual, el uso de los genéricos autorreferenciales:

class ModelBase<TModel> 
{ 
    public virtual IDictionary<string, object> GetHtmlAttributes<TProperty> 
     (Expression<Func<TModel, TProperty>> propertyExpression) 
    { 
     return new Dictionary<string, object>(); 
    } 
} 

class FooModel : ModelBase<FooModel> 
{ 
    public override IDictionary<string, object> GetHtmlAttributes<TProperty> 
     (Expression<Func<FooModel, TProperty>> propertyExpression) 
    { 
     return new Dictionary<string, object> { { "foo", "bar" } }; 
    } 
} 
-3

Usted se refiere al tipo y no a la instancia. Haga 'Modelo' minúsculas en el ejemplo en su segundo y cuarto ejemplo de código.

Model.GetHtmlAttributes 

debería ser

model.GetHtmlAttributes 
+0

gracias por la sugerencia, pero necesito darle una instancia específica de un objeto modelo (expuesta la propiedad Modelo de la vista). 'modelo' no existe en realidad en el contexto del parámetro htmlAttributes del TextBoxFor helper. –

3

C# compilador sólo tienen lambda

arg => arg.MyProperty 

para el tipo inferir de arg (TModel) un tipo de arg.MyProperty (TProperty). Es imposible.

14

tenía este mismo problema, mi solución:
En la web.fichero de configuración:

<compilation debug="true>
tuvo que ser cambiado a
<compilation debug="true" targetFramework="4.0">

+1

¡Muchas gracias Jim! Me has salvado el día, busqué en Google durante días y no encontré una solución a las preguntas principales, ¡pero luego encontré la tuya aquí en un pequeño comentario! Estoy usando VS 2012 que viene con MVC 4.0, y sí agregando el targetFramework = "4.0" resuelto los problemas con líneas rojas en ViewBag, Html.TextboxFor, etc. – Nestor

+0

Abrí una nueva [Pregunta con más título relacionado] (http : //stackoverflow.com/questions/13695497/visual-studio-red-lines-under-viewbag-and-html-textboxfor-helpers-in-views/13695498#13695498), utilizó su respuesta y tiene crédito para ello. Espero que ayude a otros. – Nestor

+0

Gracias Jim, me salvaste el día. ¿Puedes explicar por qué este targetFramework es importante? ¿Cómo resolviste esto? – Vincent

17

Sé que esta pregunta ya ha aceptado una respuesta, pero para mí, un principiante .NET, no había una solución simple a lo que era haciendo el mal y pensé que lo compartiría.

que había estado haciendo esto:

@Html.HiddenFor(Model.Foo.Bar.ID) 

Lo que funcionó para mí estaba cambiando a esto:

@Html.HiddenFor(m => m.Foo.Bar.ID) 

(donde "m" es una cadena arbitraria para representar el objeto modelo)

0

En caso de que ayude, me he encontrado con este problema al pasar null en un parámetro para un genérico TValue, para evitar esto debes convertir tus valores nulos:

(string)null 

(int)null 

etc.

4

Este error también se relaciona con un problema de caché .

que tenían el mismo problema y se resolvió simplemente limpieza y construcción la solución de nuevo.

+1

Para mí también era un problema de almacenamiento en caché, pero solo se resolvió después de reiniciar Visual Studio. Para mí, esto ocurrió después de actualizar los espacios de nombres de los modelos a los que se hace referencia. – WillemdeKok

+1

¡Encontré esto y me fue almacenado en caché! – lozzajp

Cuestiones relacionadas