为什么不'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>
?我需要做些什么才能使它工作?这是一种错误的方法,还有更好的方法吗?
最简单的修复方法就是使用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));
}