【问题标题】:Actual type cannot be inferred for the method accepting Expression<Func>无法为接受 Expression<Func> 的方法推断实际类型
【发布时间】:2013-03-15 06:14:40
【问题描述】:

我正在编写一个小型库,用于解析存储过程的结果集(基本上是一种非常特殊的 ORM)。

我有课

class ParserSetting<T> // T - type corresponding to particular resultset
{
    ...
    public ParserSettings<TChild> IncludeList<TChild, TKey>(
        Expression<Func<T, TChild[]>> listProp,
        Func<T, TKey> foreignKey,
        Func<TChild, TKey> primaryKey,
        int resultSetIdx)
    { ... }
}

这里方法IncludeList 指定结果集编号。 resultSetIdx 应该被解析为好像它由 TChild 对象组成并分配给由 listProp 表达式(作为数组)定义的属性。

我是这样使用的:

class Parent
{
   public int ParentId {get;set;}
   ...
   public Child[] Children{get;set;}
}

class Child
{
   public int ParentId {get;set;}
   ...
}
ParserSettings<Parent> parentSettings = ...;
parentSettings.IncludeList(p => p.Children, p=> p.ParentId, c => c.ParentId, 1);

这种方法很有魅力。到目前为止,一切顺利。

除了数组之外,我还想支持不同类型的集合。所以,我正在尝试添加以下方法:

    public ParserSettings<TChild> IncludeList<TChild, TListChild, TKey>(
        Expression<Func<T, TListChild>> listProp,
        Func<T, TKey> foreignKey,
        Func<TChild, TKey> primaryKey,
        int resultSetIdx)
    where TListChild: ICollection<TChild>, new()
    { ... }

但是,当我尝试按如下方式使用它时:

class Parent
{
   public int ParentId {get;set;}
   ...
   public List<Child> Children{get;set;}
}

class Child
{
   public int ParentId {get;set;}
   ...
}
ParserSettings<Parent> parentSettings = ...;
parentSettings.IncludeList(p => p.Children, p=> p.ParentId, c => c.ParentId, 1);

C# 编译器发出错误消息“无法推断方法 ParserSettings.IncludeList(...) 的类型参数”。

如果我明确指定类型,它会起作用:

parentSettings.IncludeList<Child, List<Child>, int>(
    p => p.Children, p=> p.ParentId, c => c.ParentId, 1);

但这在某种程度上违背了使调用过于复杂的目的。

有没有办法在这种情况下实现类型推断?

【问题讨论】:

  • @HamletHakobyan,我想在映射期间创建具有新集合值的属性。类似于:var childrenBuckets = childrenResultSet.ToLookup(primaryKey); foreach(parent in parentResultSet){ var value = childrenBuckets[foreignKey(parent)]; setProperty(parent, new TList{ value } ); } 如果我不能用new 创造价值,那就更难了
  • @devio 提到的传递ICollection 仍然是恕我直言的解决方法。我对这个问题的“理论”方面很感兴趣,我认为期望类型引用来解决这个问题并没有错。

标签: c# type-inference expression


【解决方案1】:

我还注意到,C# 编译器推断类型的能力不能“拐弯抹角”。

在您的情况下,您不需要任何额外的方法,只需将Child[] 重写为ICollection&lt;TChild&gt;,签名将匹配数组、列表等:

    public ParserSettings<TChild> IncludeList<TChild, TKey>(
        Expression<Func<T, ICollection<TChild>>> listProp,
        Func<T, TKey> foreignKey,
        Func<TChild, TKey> primaryKey,
        int resultSetIdx) {
            ...
        }

【讨论】:

  • 有趣。您对类型推断的此类陷阱有任何参考吗?
  • 我想在数据解析过程中在后台创建集合。这意味着理想情况下我需要特定类型(和new() 约束)或为每个属性使用Activator.CreateInstance(我希望避免)。
  • 传递一个 ICollection 工厂而不是暗示一个集合类型
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多