无法从用法中推断出类型参数。尝试明确指定类型参数

Posted

技术标签:

【中文标题】无法从用法中推断出类型参数。尝试明确指定类型参数【英文标题】:The type arguments cannot be inferred from the usage. Try specifying the type arguments explicitly 【发布时间】:2011-02-11 13:05:30 【问题描述】:

有人可以为我澄清一些事情吗?在我的 ASP.NET MVC 2 应用程序中,我有一个 BaseViewModel 类,其中包括以下方法:

public virtual IDictionary<string, object> GethtmlAttributes<TModel, TProperty>
                        (Expression<Func<TModel, TProperty>> propertyExpression)

    return new Dictionary<string, object>();

想法是每个子视图模型都可以覆盖此方法并根据某些逻辑提供一组合适的 html 属性,以在视图中呈现:

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

但是,在上面一行中使用时,当我点击视图时出现编译错误:

方法“...BaseViewModel.GetHtmlAttributes&lt;TModel,TProperty&gt; Expression&lt;System.Func&lt;TModel,TProperty&gt;)”的类型参数无法从用法中推断出来。尝试明确指定类型参数。

我必须做到以下几点:

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

我只是想弄清楚它如何尝试推断类型,在HtmlHelper/TextBoxFor 扩展方法中这样做没有问题吗?

是不是因为视图中的HtmlHelper 将自动与页面顶部ViewUserControl 中指定的类型相同,而我的代码可以用于从BaseViewModel 继承的任何类型?是否可以以可以推断我的模型/属性类型的方式编写此代码?

【问题讨论】:

神圣的水平滚动条蝙蝠侠! 是的。在我们的 30 英寸显示器上,我们只有 6.5 英寸的显示器用于在这些小窗口中来回滚动代码,这太荒谬了。来吧 SA 伙计们,拿走你的 VC 钱并获得动态页面大小! 【参考方案1】:

我知道这个问题已经有一个公认的答案,但是对于我,一个 .NET 初学者来说,有一个简单的解决方案可以解决我做错的事情,我想我会分享。

我一直在这样做:

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

对我有用的是改变这个:

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

(其中“m”是表示模型对象的任意字符串)

【讨论】:

【参考方案2】:

在您的示例中,编译器无法知道 TModel 应该是什么类型。你可以做一些接近你可能试图用扩展方法做的事情。

static class ModelExtensions

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

但我认为,您将无法拥有类似于 virtual 的任何东西。

编辑:

其实你可以virtual,使用自引用泛型:

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"  ;
    

【讨论】:

这在这种情况下可以正常工作,但对于某些 HtmlHelper 扩展来说是不可接受的。事实上,我创建了以下扩展名:public static IHtmlContent EnumCheckBoxListFor&lt;TModel, TEnum&gt;(this IHtmlHelper&lt;TModel&gt; htmlHelper, Expression&lt;Func&lt;TModel, IEnumerable&lt;TEnum&gt;&gt;&gt; expression, object htmlAttributes = null) 。在这种情况下,我不能使用虚拟/覆盖解决方法(而且我看不到任何“干净”的解决方案)。请注意,当我在视图中调用它时,可以推断出模型类型,而不能推断出枚举类型。【参考方案3】:

我遇到了同样的问题,我的解决方案: 在 web.config 文件中:

&lt;compilation debug="true&gt; 不得不改成&lt;compilation debug="true" targetFramework="4.0"&gt;

【讨论】:

非常感谢吉姆!你拯救了我的一天,我在谷歌上搜索了几天并没有找到主要问题的解决方案,但然后在一个小评论中找到你的解决方案!我正在使用 MVC 4.0 附带的 VS 2012,是的,添加 targetFramework="4.0" 解决了 ViewBag、Html.TextboxFor 等下的红线问题。 我打开了一个新的Question with more related title,使用了您的答案并对此表示赞赏。希望对其他人有所帮助。 谢谢吉姆,你拯救了我的一天。你能解释一下为什么这个 targetFramework 很重要吗?你是怎么想出来的?【参考方案4】:

此错误也与 缓存 问题有关。

我遇到了同样的问题,只是清理并再次构建解决方案就解决了。

【讨论】:

对我来说这也是一个缓存问题,但它只有在重新启动 Visual Studio 后才得到解决。对我来说,这发生在更新被引用模型的命名空间之后。 碰到这个,它也在为我缓存!【参考方案5】:

C# 编译器只有 lambda

arg => arg.MyProperty

推断 arg(TModel) 的类型是 arg.MyProperty(TProperty) 的类型。这是不可能的。

【讨论】:

【参考方案6】:

我实际上是在寻找类似的错误,Google 将我发送到此问题。 错误是:

方法的类型参数 'IModelExpressionProvider.CreateModelExpression(ViewDataDictionary, Expression>)' 无法从用法推断出

我花了大约 15 分钟试图弄清楚。它发生在 Razor .cshtml 视图文件中。 由于编译器并没有太大帮助,我不得不对视图代码的某些部分进行注释才能到达它所发出的声音。

<div class="form-group col-2">
    <label asp-for="Organization.Zip"></label>
    <input asp-for="Organization.Zip" class="form-control">
    <span asp-validation-for="Zip" class="color-type-alert"></span>
</div>

你能认出来吗?是的...我重新检查了两次,一开始没有得到它!

查看 ViewModel 的属性只是 Zip,而它应该是 Organization.Zip。就是这样。

所以重新检查您的视图源代码... :-)

【讨论】:

谢谢你。我在这里遇到了同样的问题,这个答案对我帮助很大。看起来在“asp-for”或“asp-validation-for”上使用不存在的属性名称会导致该异常。【参考方案7】:

如果有帮助,我在将null 传递给通用TValue 的参数时遇到了这个问题,要解决这个问题,您必须强制转换空值:

(string)null

(int)null

等等

【讨论】:

【参考方案8】:

只是为了添加另一个可能的解决方案/问题,我正在更新密码,但数据库模型没有任何密码属性,所以我创建了一个视图模型。

 <div class="form-group">
            <label asp-for="user.Password"></label>
            <input asp-for="user.Password" class="form-control" />
            <span asp-validation-for="user.Password" class="text-danger"></span>
  </div>

【讨论】:

【参考方案9】:

您指的是类型而不是实例。在第二个和第四个代码示例的示例中将“模型”设为小写。

Model.GetHtmlAttributes

应该是

model.GetHtmlAttributes

【讨论】:

感谢您的建议,但我需要给它一个模型对象的特定实例(公开视图的模型属性)。 'model' 实际上并不存在于 TextBoxFor 帮助器的 htmlAttributes 参数的上下文中。

以上是关于无法从用法中推断出类型参数。尝试明确指定类型参数的主要内容,如果未能解决你的问题,请参考以下文章

通用扩展方法:无法从用法推断类型参数

C# 泛型方法类型参数不是从用法中推断出来的

在 TypeScript 中,如何在具有多个类型参数的方法中推断出泛型类型参数?

打字稿泛型:从函数参数的类型推断类型?

为啥 C# 无法从非泛型静态方法的签名推断泛型类型参数类型?

TypeScript 类型推导及类型兼容性