2017-09-01 60 views
1

我有一個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>'

我嘗試各種組合,但我還是沒能設法避免錯誤。我想在這裏做不可能的事,還是有一種簡單的做我想做的事?你提到(IHeaderDictionaryIFormCollectionIQueryCollection)所有

+0

如果你改變'ParseKeys'採取'的IDictionary <字符串會發生什麼, StringValues> dict'而不是?或者'IEnumerable > dict'? – mjwills

+0

您如何期待'dict [key]'在這裏轉換爲字符串?例如,如果字典包含一堆複雜的類對象,例如? – DavidG

+0

但是你提到的所有3種類型都實現了'IEnumerable >'所以你真的不需要泛型方法。 – DavidG

回答

4

這些集合實現相同的接口: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); 
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)); 
+0

爲什麼使用IEnumerable >'over over IEnumerable >'? – mjwills

+0

取決於您正在使用的[IFormCollection](https://msdn.microsoft.com/en-us/library/microsoft.owin.iformcollection(v = vs.113).aspx)。 – Sefe

+1

OP使用.NET Core - 而不是「IFormCollection」。 – mjwills

相關問題