為什麼Select()不轉換IEnumerable 到IEnumerable

c# dapper linq

我正在嘗試使用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> ?我需要做些什麼來完成這項工作?這只是錯誤的方法而且有更好的方法嗎?

一般承認的答案

最簡單的解決方法是使用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> - 我相信它會起作用......

編輯:如註釋中所述,強制在編譯時解析方法調用也將修復它。基本上它取決於你發現最可讀的東西。


熱門答案

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


許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因