简体   繁体   English

为什么Select()不转换IEnumerable <dynamic> 到IEnumerable <StrongType> ?

[英]Why doesn't Select() convert a IEnumerable<dynamic> to IEnumerable<StrongType>?

I'm trying to use Dapper simply to map my database tables to types in C#, however, some of my types need additional elements that are not in the table. 我正在尝试使用Dapper简单地将我的数据库表映射到C#中的类型,但是,我的一些类型需要不在表中的其他元素。 To do this I am using a factory that can take column values and set the appropriate properties. 为此,我使用的工厂可以获取列值并设置适当的属性。

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

Currently this is resulting the return statement generating an error: 目前这导致return语句生成错误:

Cannot convert expression type 'System.Collections.Generic.IEnumerable<dynamic>' to return type 'System.Collections.Generic.IEnumerable<IMyType>' 无法将表达式类型'System.Collections.Generic.IEnumerable<dynamic>'为返回类型'System.Collections.Generic.IEnumerable<IMyType>'

My factory class looks something like this: 我的工厂类看起来像这样:

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));
  }
}

Why doesn't the Select() method return IEnumerable<IMyType> ? 为什么Select()方法不返回IEnumerable<IMyType> What do I need to do to make this work? 我需要做些什么来完成这项工作? Is this just the wrong approach and there's a better way? 这只是错误的做法,还有更好的方法吗?

The simplest fix is just to use the Cast<> LINQ operator: 最简单的解决方法就是使用Cast<> LINQ运算符:

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

Alternatively, you could cast each element: 或者,您可以投射每个元素:

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

It doesn't currently work because there's simply no implicit conversion available between IEnumerable<dynamic> and IEnumerable<IMyType> . 它当前不起作用,因为IEnumerable<dynamic>IEnumerable<IMyType>之间根本没有可用的隐式转换。 IEnumerable<dynamic> could be implemented in any number of ways, and given that each item will be generated dynamically there's no reason to suppose the result value will implement IEnumerable<IMyType> . IEnumerable<dynamic>可以以多种方式实现,并且假设每个项目将动态生成,则没有理由假设结果值将实现IEnumerable<IMyType>

I agree that it looks like the second form isn't actually adding anything, but the compiler doesn't check all the possible return types of _myTypeFactory.Create(o) - it treats that whole expression as a dynamic value, ie the expression is of type dynamic . 我同意它看起来第二种形式实际上并没有添加任何东西,但是编译器没有检查_myTypeFactory.Create(o)所有可能的返回类型 - 它将整个表达式视为动态值,即表达式是类型dynamic Therefore the Select result is still of type IEnumerable<dynamic> . 因此, Select结果仍然是IEnumerable<dynamic>类型。

Another option is to specify the generic type argument to Select . 另一个选项是为Select指定泛型类型参数。

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

That's attempting to force the lambda expression to a Func<dynamic, IMyType> - I believe that will work... 那是试图将lambda表达式强制为Func<dynamic, IMyType> - 我相信它会起作用......

EDIT: As noted in comments, forcing the method invocation to be resolved at compile-time will fix it too. 编辑:如注释中所述,强制在编译时解析方法调用也将修复它。 Basically it depends what you find most readable. 基本上它取决于你发现最可读的东西。

The best fix is probably to remove the dynamic invocation from the select statement then you'll get your expected static type IEnumerable<IMyType> . 最好的解决方法可能是从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
}

OR 要么

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)); 
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM