为什么不't Select()转换IEnumerableIEnumerable< Strong

本文关键字:IEnumerable 转换 dynamic Strong Select 为什么不 | 更新日期: 2023-09-27 18:06:58

我试图使用Dapper简单地将我的数据库表映射到c#中的类型,然而,我的一些类型需要表中没有的额外元素。为了做到这一点,我使用了一个工厂,它可以接受列值并设置适当的属性。

public IEnumerable<IMyType> All() {
  var query = _connection.Query("SELECT * FROM [table]");
  return query.Select(o => _myTypeFactory.Create(o));
}

当前这会导致返回语句生成一个错误:

不能将表达式类型'System.Collections.Generic.IEnumerable<dynamic>'转换为返回类型'System.Collections.Generic.IEnumerable<IMyType>'

我的工厂类看起来像这样:

public class MyTypeFactory {
  public IMyType Create(dynamic o) {
    return Create((String) o.Code, (Int32) o.KeyID);
  }
  public IMyType Create(String code, Int32 keyID) {
    return new MyType(code, Cache.Lookup(keyID));
  }
}

为什么Select()方法不返回IEnumerable<IMyType> ?我需要做些什么才能使它工作?这是一种错误的方法,还有更好的方法吗?

为什么不't Select()转换IEnumerable<dynamic>IEnumerable< Strong

最简单的修复方法就是使用Cast<> LINQ运算符:

public IEnumerable<IMyType> All() {
  var query = _connection.Query("SELECT * FROM [table]");
  return query.Select(o => _myTypeFactory.Create(o))
              .Cast<IMyType>();
}

或者,您可以强制转换每个元素:

public IEnumerable<IMyType> All() {
  var query = _connection.Query("SELECT * FROM [table]");
  return query.Select(o => (IMyType) _myTypeFactory.Create(o));
}

它目前不起作用,因为IEnumerable<dynamic>IEnumerable<IMyType>之间根本没有隐式转换。IEnumerable<dynamic>可以以多种方式实现,并且考虑到每项都将动态生成,因此没有理由假设结果值将实现IEnumerable<IMyType>

我同意它看起来就像第二种形式实际上并没有添加任何东西,但是编译器不会检查_myTypeFactory.Create(o)的所有可能的返回类型-它将整个表达式视为动态值,即表达式的类型为dynamic。因此Select的结果仍然是IEnumerable<dynamic>的类型。

另一个选项是将泛型类型参数指定给Select

public IEnumerable<IMyType> All() {
  var query = _connection.Query("SELECT * FROM [table]");
  return query.Select<IMyType>(o => _myTypeFactory.Create(o));
}

这是试图强制lambda表达式为Func<dynamic, IMyType> -我相信将工作…

EDIT:正如在注释中所指出的,强制在编译时解析方法调用也会修复它。基本上,这取决于你觉得什么最易读。

最好的修复方法可能是从select语句中删除动态调用,然后您将获得预期的静态类型IEnumerable<IMyType>

public IEnumerable<IMyType> All() {
  var query = _connection.Query("SELECT * FROM [table]");
  return query.Select(o => _myTypeFactory.Create((Object)o)); //cast dynamic type to Object
}

public IEnumerable<IMyType> All() {
      IEnumerable<object> query = _connection.Query("SELECT * FROM [table]"); //IEnumerable<dynamic> is the same as IEnumerable<object>
      return query.Select(o => _myTypeFactory.Create(o)); 
}
相关文章: