如何使用一种通用方法迭代不同类型的字典?

时间:2017-09-01 10:42:15

标签: c# generics asp.net-core

我有一个HttpContext context并且我遍历了一些Request属性来收集信息。目前我这样做:

if (context.Request.Headers?.Keys != null)
{
    var items = new StringBuilder();
    foreach (var key in context.Request.Headers.Keys)
    {
        items.AppendLine(key + " = " + context.Request.Headers[key]);
    }
    result.Headers = items.ToString();
}
if (context.Request.Form?.Keys != null)
{
    var items = new StringBuilder();
    foreach (var key in context.Request.Form.Keys)
    {
         items.AppendLine(key + " = " + context.Request.Form[key]);
    }
    result.Form = items.ToString();
}
if (context.Request.Query?.Keys != null)
{
    var items = new StringBuilder();
    foreach (var key in context.Request.Query.Keys)
    {
        items.AppendLine(key + " = " + context.Request.Query[key]);
    }
    result.Query = items.ToString();
}

我想将这个重复的代码转换为通用方法(如果你可以建议任何其他方式,我也可以使用它们)。我尝试编写通用方法:

private static string ParseKeys<T>(IDictionary<object, object> dict)
{
    var sb = new StringBuilder();
    foreach (var key in dict.Keys)
    {
        sb.AppendLine(key + " = " + dict[key]);
    }
    return sb.ToString();
}

并将其称为:

result.Headers = ParseKeys<IHeaderDictionary>(context.Request.Headers);
result.Form = ParseKeys<IFormCollection>(context.Request.Form);
result.Query = ParseKeys<IQueryCollection>(context.Request.Query);

但是我收到了这样的错误:cannot convert from 'Microsoft.AspNetCore.Http.IHeaderDictionary' to 'System.Collections.Generic.IDictionary<object, object>'

我尝试了各种组合,但我仍然无法避免错误。我想在这里做不可能,还是有一个简单的做我想做的事情?

2 个答案:

答案 0 :(得分:5)

您提到的那些集合(IHeaderDictionaryIFormCollectionIQueryCollection)都实现了相同的界面:IEnumerable<KeyValuePair<string, StringValues>>所以这里您不需要通用方法。相反,你可以做这样的事情:

private static string ParseKeys(IEnumerable<KeyValuePair<string, StringValues>> values)
{
    var sb = new StringBuilder();
    foreach (var value in values)
    {
        sb.AppendLine(value.Key + " = " + string.Join(", ", value.Value));
    }
    return sb.ToString();
}

并像以前一样调用它:

result.Headers = ParseKeys(context.Request.Headers);
result.Form = ParseKeys(context.Request.Form);
result.Query = ParseKeys(context.Request.Query);

答案 1 :(得分:0)

您使用的是通用方法,但未使用泛型类型参数T。至于IHeaderDictionaryIFormCollection,接受IEnumerable<KeyValuePair<string, string[]>>就足够了,因为两个接口都会继承它:

private static string ParseKeys(IEnumerable<KeyValuePair<string, string[]>> dict)
{
    var sb = new StringBuilder();
    foreach (var keyValuePair in dict)
    {
        sb.AppendLine(keyValuePair.Key + " = " + String.Join(", ", keyValuePair.Value));
    }
    return sb.ToString();
}

IQueryCollection而言,它是IEnumerable<KeyValuePair<string, StringValues>>。您可以使用迭代器轻松将其转换为所需类型:

private static IEnumerable<KeyValuePair<string, string[]>> Transform(IEnumerable<KeyValuePair<string, StringValues>> source) {
    foreach(var item in source) {
        yield return new KeyValuePair<string, string[]>(item.Key, item.Value.ToArray());
    }
}

最终,您可以调用以下方法:

result.Headers = ParseKeys(context.Request.Headers);
result.Form = ParseKeys(context.Request.Form);
result.Query = ParseKeys(Transform(context.Request.Query));