6

我试图简单地使用 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>?我需要做什么才能完成这项工作?这只是错误的方法,还有更好的方法吗?

4

2 回答 2

10

最简单的解决方法就是使用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结果仍然是 type 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>- 我相信这会起作用......

编辑:如评论中所述,强制在编译时解析方法调用也将修复它。基本上,这取决于您认为最易读的内容。

于 2011-08-30T18:11:02.620 回答
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)); 
}
于 2011-08-30T18:21:11.520 回答