web-dev-qa-db-fra.com

Les arguments de type ne peuvent pas être déduits de l'utilisation. Essayez de spécifier explicitement les arguments de type

Quelqu'un pourrait-il clarifier quelque chose pour moi? Dans mon application ASP.NET MVC 2, j'ai une classe BaseViewModel qui inclut la méthode suivante:

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

L'idée étant que chaque viewmodel enfant peut remplacer cette méthode et fournir un ensemble approprié d'attributs html, basés sur une logique, à rendre dans la vue:

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

Cependant, lorsqu'il est utilisé comme dans la ligne ci-dessus, j'obtiens une erreur de compilation lorsque j'appuie sur la vue:

Les arguments de type pour la méthode '...BaseViewModel.GetHtmlAttributes<TModel,TProperty> Expression<System.Func<TModel,TProperty>) 'ne peut pas être déduit de l'utilisation. Essayez de spécifier explicitement les arguments de type.

Je dois faire ce qui suit:

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

Je cherche juste une certaine clarté sur la façon dont il essaie d'inférer le type, il n'a aucun problème à le faire dans le HtmlHelper/TextBoxFor méthode d'extension?

Est-ce parce que HtmlHelper dans la vue sera automatiquement pour le même type que celui spécifié dans ViewUserControl en haut de la page, alors que mon code peut être pour tout type héritant de BaseViewModel? Est-il possible d'écrire ceci de manière à pouvoir déduire mes types de modèle/propriété?

34
Veli Gebrev

Dans votre exemple, le compilateur n'a aucun moyen de savoir quel type doit être TModel. Vous pouvez faire quelque chose de proche de ce que vous essayez probablement de faire avec une méthode d'extension.

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

Mais vous ne pourriez pas avoir quelque chose de similaire à virtual, je pense.

MODIFIER:

En fait, vous pouvez faire virtual, en utilisant des génériques auto-référentiels:

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" } };
    }
}
14
svick

Je sais que cette question a déjà une réponse acceptée, mais pour moi, un débutant .NET, il y avait une solution simple à ce que je faisais mal et je pensais que je partagerais.

J'avais fait ça:

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

Ce qui a fonctionné pour moi était en train de changer:

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

(où "m" est une chaîne arbitraire pour représenter l'objet modèle)

17
inanutshellus

J'ai eu ce même problème, ma solution:
Dans le fichier web.config:

<compilation debug="true>
a dû être remplacé par
<compilation debug="true" targetFramework="4.0">

14
Jim

Cette erreur est également liée à un problème cache.

J'ai eu le même problème et il a été résolu juste nettoyage et bâtiment la solution à nouveau.

4
Zanon

Le compilateur C # n'a que lambda

arg => arg.MyProperty

pour déduire le type d'arg (TModel) un type d'arg.MyProperty (TProperty). C'est impossible.

3
Ziav

Au cas où cela aiderait, j'ai rencontré ce problème en passant null dans un paramètre pour un générique TValue, pour contourner ce problème, vous devez convertir vos valeurs nulles:

(string)null

(int)null

etc.

0
DevDave