为什么Select()不将IEnumerable <dynamic>转换为IEnumerable <strongtype>?</strongtype> </dynamic>

时间:2011-08-30 18:08:09

标签: c# linq dapper

我正在尝试使用Dapper简单地将我的数据库表映射到C#中的类型,但是,我的一些类型需要不在表中的其他元素。为此,我使用的工厂可以获取列值并设置适当的属性。

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

目前这导致return语句产生错误:

无法将表达式类型'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>?我需要做些什么来完成这项工作?这只是错误的做法而且还有更好的方法吗?

2 个答案:

答案 0 :(得分:9)

最简单的解决方法是使用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>

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

另一个选择是指定IEnumerable<dynamic>的泛型类型参数。

Select

那是试图强制lambda表达式为public IEnumerable<IMyType> All() { var query = _connection.Query("SELECT * FROM [table]"); return query.Select<IMyType>(o => _myTypeFactory.Create(o)); } - 我相信会起作用......

编辑:正如评论中所述,强制在编译时解析方法调用也会修复它。基本上它取决于你认为最具可读性的内容。

答案 1 :(得分:1)

最好的解决方法可能是从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)); 
}