如何实现通用 IEnumerable 或 IDictionary 以避免 CA1006?

Posted

技术标签:

【中文标题】如何实现通用 IEnumerable 或 IDictionary 以避免 CA1006?【英文标题】:How to implement generic IEnumerable or IDictionary to avoid CA1006? 【发布时间】:2011-11-15 14:44:59 【问题描述】:

出于好奇,我想知道如何最好地实现一个可以用来避免 CA1006 警告的类

CA1006:Microsoft.Design:考虑一个设计,其中“IReader.Query(String, String)”不嵌套泛型类型“IList(Of IDictionary(Of String, Object))”。

这是返回泛型类型的方法

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

类似

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

编辑:

按照 Marc 的建议,我将嵌套泛型封装在此类中

public class QueryRow : List<KeyValuePair<string, object>>

    protected internal QueryRow(IEnumerable<KeyValuePair<string, object>> dictionary)
    
        this.AddRange(dictionary.Select(kvp => kvp));
    

【问题讨论】:

这里的字典列表的意图是什么?是那些带有键值的行(即按列名访问的单元格)? 每个字典都是一行,其中每个键是列标题,值是单元格值 可以不用.Cast代替.ToDictionary吗? 【参考方案1】:

首先,请注意这是一个设计指南,而不是编译器错误。一种有效的方法是:忽略它。

另一个可能是 - 封装它;即返回一个List&lt;QueryRow&gt;,其中QueryRow 是带有索引器的IDictionary&lt;string,object&gt; 的浅包装,即

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; 
    

然后,由于这是通过 dapper 访问的,请通过以下方式填充:

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

另一个选项(我不太喜欢)可能是:返回 DataTable

在输入DataTable 后去洗手了...嘎!现在两次

【讨论】:

好的,我试过这样。不工作。我在添加无参数构造函数时收到此消息System.ArgumentNullException: Parametername: con bei System.Reflection.Emit.DynamicILGenerator.Emit(OpCode opcode, ConstructorInfo con) bei Dapper.SqlMapper.GetClassDeserializer(IDataReader reader, Int32 startBound, Int32 length, Boolean returnNullIfFirstMissing) in SqlMapper.cs: line 1227.,Query 返回一个 IEnumerable 但 value 属性为 null。 @mrt 哇,完全没有注意到这是“精致”。原始问题中没有任何内容向我暗示“精致”!但是:在这种情况下,您应该能够使用非通用 Query() 方法,然后依次转换每个方法,即connection.Query(....).Select(x =&gt; new QueryRow((IDictionary&lt;string,object&gt;)x).ToList() - 有什么用吗? 我认为标签简洁明了:) @mrt181 我显然错过了标签

以上是关于如何实现通用 IEnumerable 或 IDictionary 以避免 CA1006?的主要内容,如果未能解决你的问题,请参考以下文章

返回一个通用的 IEnumerable<T>

在 C# 中:如何声明一个类型为键的通用字典,该类型的 IEnumerable<> 作为值?

将通用List / Ienumerable转换为DataTable?

如何在 Asp.NET MVC 视图名称空间中使用 List 或 IList 代替 IEnumerable?

如何从 C# 中的同一方法返回字符串以及 IEnumerable<T>? [复制]

foreach遍历访问的对象必须实现IEnumerable 或声明GetEnumerator