2011-11-15 12 views
9

Z ciekawości chciałbym wiedzieć, jak najlepiej wdrożyć klasy, które mogłyby zostać wykorzystane w celu uniknięcia ostrzeżenie CA1006Jak wdrożyć ogólne IEnumerable lub IDictionary, aby uniknąć CA1006?

CA1006: Microsoft.Design: Rozważmy projekt, w którym „IReader.Query (String, String) "nie zagnieżdża typu ogólnego" IList (Of IDictionary (Of String, Object)).

Jest to metoda, która zwraca typ rodzajowy

public virtual IList<IDictionary<string, object>> Query(
    string fullFileName, 
    string sheetName) 
{ 
    using (var connection = new OdbcConnection(
     this.GetOdbcConnectionString(fullFileName))) 
    { 
     connection.Open(); 
     return connection 
      .Query(string.Format(
       CultureInfo.InvariantCulture, 
       SystemResources.ExcelReader_Query_select_top_128___from__0_, 
       sheetName)) 
      .Cast<IDictionary<string, object>>() 
      .ToList(); 
    } 
} 

Coś

SourceData<T, U> Query(string fullFileName, string sheetName) 
SourceData Query(string fullFileName, string sheetName) 

EDIT:

Po sugestii Marca ja zamknięty zagnieżdżona generycznych w tej klasie

public class QueryRow : List<KeyValuePair<string, object>> 
{ 
    protected internal QueryRow(IEnumerable<KeyValuePair<string, object>> dictionary) 
    { 
     this.AddRange(dictionary.Select(kvp => kvp)); 
    } 
} 
+0

jaka jest intencja listy słowników tutaj? to są wiersze z wartościami kluczowymi (tj. komórkami dostępnymi po nazwie kolumny)? –

+0

każdy słownik jest wierszem gdzie każdy klucz jest nagłówkiem kolumny, a wartość jest wartością komórki – mrt181

+0

W miejsce '.Cast' nie możesz użyć' .ToDictionary'? – IAbstract

Odpowiedz

12

Po pierwsze, należy pamiętać, że jest to projekt wytyczna, a nie błąd kompilatora. Jednym z ważnych podejść byłoby: zignoruj ​​to.

Inna może być - hermetyzować; tj zwracają List<QueryRow> gdzie QueryRow jest płytką owijki ponad IDictionary<string,object> z podziałowym, tj

public class QueryRow { 
    private readonly IDictionary<string,object> values; 
    internal QueryRow(IDictionary<string,object> values) { 
     this.values = values; 
    } 
    public object this[string key] { 
     get { return values[key]; } 
     set { values[key] = value; } 
    } 
} 

następnie, ponieważ jest on uzyskiwany za pomocą Dappera wypełnić za pomocą:

var data = connection.Query(....) 
     .Select(x => new QueryRow((IDictionary<string,object>)x).ToList() 

innego wariantu (tj Nie jestem bardzo lubi), może być: powrót DataTable.

idzie umyć ręce po wpisaniu DataTable ... gah! dwa razy teraz

+0

i prawie wymiotowałem, kiedy czytam powrót DataTable;) – mrt181

+0

ok, próbowałem go w ten sposób. Nie działa. I ten komunikat 'System.ArgumentNullException: ParameterName: con bei System.Reflection.Emit.DynamicILGenerator.Emit (OpCode opcode, ConstructorInfo con) bei Dapper.SqlMapper.GetClassDeserializer (czytnik IDataReader, Int32 startBound, długość Int32, Boolean returnNullIfFirstMissing) w SqlMapper.cs: wiersz 1227. "Kiedy dodaję konstruktor bez parametrów, zapytanie zwraca wartość IEnumerable , ale właściwość value ma wartość null. – mrt181

+0

@mrt woah, całkowicie nie zauważyłem, że był "elegancki". Nic w pierwotnym pytaniu nie sugerowało mi "eleganckiego"! Ale: w tym przypadku powinieneś móc używać nietypowej metody Query(), a następnie rzutować po kolei, np. 'Connection.Query (....). Wybierz (x => new QueryRow ((IDictionary ) x) .ToList() '- dowolne użycie? –

Powiązane problemy