【问题标题】:Need help making this method (using string.Join() and LINQ) into a generic one需要帮助将此方法(使用 string.Join() 和 LINQ)变成通用方法
【发布时间】:2019-09-08 11:05:28
【问题描述】:

我编写了一个函数,将 DataTable 的值转换为格式为“value1, value2, value3, ...”的字符串。该函数还接受 columnindex 以及一个环绕符(通常是“'”)作为参数。

我不想为此函数编写许多不同的变体(例如,一个带有数据集,一个带有列表等),我只想为此创建一个通用函数。

我已经尝试将 IEnumerable 添加到函数头,但随后在函数内部出现“无法使用 [] 将索引应用到类型为 'T' 的表达式”错误。

我认为我需要为此创建一个界面(?),但我对此没有太多/任何经验。

这是我想把原来的函数变成一个通用函数:

public static string GenerateWhereInListFromData(DataTable dt_data, int columnIndex, string separator)
{
    string resultList = string.Join(", ", dt_data.AsEnumerable().Select(tmp => separator + tmp[columnIndex].ToString() + separator));

    return resultList;
}

谁能帮忙把它变成一个通用函数,它可以将数据集、数据表、字符串数组、列表和可能的其他东西作为输入参数?

【问题讨论】:

  • 如果你这样做是为了生成一个 sql 查询.. WHERE Column IN ('value1', 'value2', 'value3', ...) - 不要这样做,因为可能存在 Sql Injection 和性能原因。相反,您可以使用Table-Valued Parameters

标签: c# string linq generics join


【解决方案1】:

要使泛型函数起作用,您需要找到一个适用于所有传入类型的接口,例如 iList、ICollection、IEnumerable 等。如果找不到所有这些类型的接口,请尝试检查对象的为所有这些接口键入并具有将数据复制到您然后加入的列表的代码。

【讨论】:

    【解决方案2】:

    简短的解释:

    也许您失败的 Methode 看起来像:

    public static string GenerateWhereInListFromDataFail<T>(IEnumerable<T> dt_data, int columnIndex, string separator) 
            {
                return string.Join(", ", dt_data.Select(tmp => separator + tmp[columnIndex].ToString() + separator));;
            }
    

    因此,您遇到的问题是列的访问器。 解决问题的一种方法是委派工作。

    public static string GenerateWhereInListFromData<T>(IEnumerable<T> dt_data, Func<T, string> columnAccessor, string separator) 
        {
            return string.Join(", ", dt_data.Select(tmp => separator + columnAccessor(tmp) + separator));;
        }
    

    方法的调用如下:

    GenerateWhereInListFromData(new List<System.Data.DataRow>(), t => t[0].ToString(), ",");
    

    希望能帮到你。

    编辑部分:


    回答您评论中的问题。 您不需要定义其他一些方法来与不同类型进行交互。 你只需要确定你可以使用所有的 IEnumerable。

    也许一些代码可以解释我想说的话:

    System.Data.DataSet dataSet = null;
    var result = GenerateWhereInListFromData(dataSet.Tables.Cast<System.Data.DataTable>(), t => t.TableName, ",");
    
    System.Data.DataTable dataTable = null;
    result = GenerateWhereInListFromData(dataTable.Rows.Cast<System.Data.DataRow>(), t => t["SomeColumn"].ToString(), ",");
    result = GenerateWhereInListFromData(dataTable.Columns.Cast<System.Data.DataColumn>(), t => t.ColumnName, ",");
    

    扩展方法 .Cast() 做得很好。它将所有内部对象转换为某个 IEnumerable。

    所以结果可能如下所示:

    表1,表2,表3,

    值1,值2,值3,

    第 1 列,第 2 列,第 3 列,

    【讨论】:

    • 您好,感谢您的详细回复!是的,我的“失败”方法看起来很像!我对委派还是很陌生,我知道它本质上是一个指向函数的指针,但我仍然缺乏任何实践。我是否必须编写一个函数 columnAccess 接受泛型并返回一个字符串,然后在里面添加 DataTable、DataSet 等的所有案例?你能提供一个简单的例子吗?
    • 非常感谢!我以为我需要定义另一种方法,但它基本上只是作为 lambda 表达式传递。所以我注意到我也可以将 DataTable 作为 dt.AsEnumerable() 或 DataSet 作为 ds.Tables[xxx].AsEnumerable() 传入。这就是我需要的。谢谢:-)
    猜你喜欢
    • 2013-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-10
    • 1970-01-01
    • 1970-01-01
    • 2023-02-03
    相关资源
    最近更新 更多