Namevaluecollection, который делает доступными для запросов LINQ
Как сделать NameValueCollection доступно для оператора запроса LINQ, например where, join, groupby?
я попробовал ниже:
private NameValueCollection RequestFields()
{
NameValueCollection nvc = new NameValueCollection()
{
{"emailOption: blah Blah", "true"},
{"emailOption: blah Blah2", "false"},
{"nothing", "false"},
{"nothinger", "true"}
};
return nvc;
}
public void GetSelectedEmail()
{
NameValueCollection nvc = RequestFields();
IQueryable queryable = nvc.AsQueryable();
}
но я ArgumentException говорила, что источник не IEnumerable.
7 ответов:
вам нужно "поднять" необщего
IEnumerableдоIEnumerable<string>. Было высказано предположение, что вы используетеOfTypeно это метод фильтрации. То, что вы делаете, является эквивалентом гипса, для которого естьCastоператор:var fields = RequestFields().Cast<string>();как отметил Франс, это обеспечивает только доступ к ключам. Вам все равно нужно будет индексировать в коллекцию для значений. Вот метод расширения для извлечения
KeyValuePairСNameValueCollection:public static IEnumerable<KeyValuePair<string, string>> ToPairs(this NameValueCollection collection) { if(collection == null) { throw new ArgumentNullException("collection"); } return collection.Cast<string>().Select(key => new KeyValuePair<string, string>(key, collection[key])); }Edit: в ответ на запрос @Ruben Bartelink, вот как получить доступ к полному набору значений для каждого ключа с помощью
ToLookup:public static ILookup<string, string> ToLookup(this NameValueCollection collection) { if(collection == null) { throw new ArgumentNullException("collection"); } var pairs = from key in collection.Cast<String>() from value in collection.GetValues(key) select new { key, value }; return pairs.ToLookup(pair => pair.key, pair => pair.value); }
AsQueryableдолжноIEnumerable<T>общий.NameValueCollectionосуществляетIEnumerable, которая отличается.вместо этого:
{ NameValueCollection nvc = RequestFields(); IQueryable queryable = nvc.AsQueryable(); }попробовать OfType (он принимает не универсальный интерфейс)
{ NameValueCollection nvc = RequestFields(); IEnumerable<string> canBeQueried = nvc.OfType<string>(); IEnumerable<string> query = canBeQueried.Where(s => s.StartsWith("abc")); }
словарь, вероятно, на самом деле ближе к тому, что вы хотите использовать, так как он фактически заполнит больше ролей, которые заполняет NameValueCollection. Это вариация решения Брайана Уоттса:
public static class CollectionExtensions { public static IDictionary<string, string> ToDictionary(this NameValueCollection source) { return source.Cast<string>().Select(s => new { Key = s, Value = source[s] }).ToDictionary(p => p.Key, p => p.Value); } }
Я знаю, что опаздываю на вечеринку, но просто хотел добавить свой ответ, который не связан с
.Castметод расширения, но вместо этого использует свойство AllKeys:var fields = RequestFields().AllKeys;Это позволит использовать следующий метод расширения:
public static IEnumerable<KeyValuePair<string, string>> ToPairs(this NameValueCollection collection) { if(collection == null) { throw new ArgumentNullException("collection"); } return collection.AllKeys.Select(key => new KeyValuePair<string, string>(key, collection[key])); }надеюсь, что это поможет будущим посетителям
проблема в том, что коллекция реализует
IEnumerable(вместоIEnumerable<T>) и перечисление коллекции возвращает ключи, а не пары.на вашем месте я бы использовал
Dictionary<string, string>который является перечислимым и может быть использован с LINQ.
для меня, @Bryan Watts ' (+1'd) ответ
ToLookupвариант представляет собой на сегодняшний день самый ясный подход для использования его только для чтения.для моего варианта использования Я манипулирую строкой запроса для использования с Linq2Rest а также нужно превратить все это обратно в
NameValueCollectionВ конце концов, так что у меня есть набор методов расширения дляNameValueCollectionкоторые предлагают более детальные операции (для работы как на имя параметра (AsEnumerable) и на аргумент (AsKeyValuePairs)), а также обратная операция преобразования его обратноToNameValueCollection(либо представительства)).пример потребления:
public static NameValueCollection WithoutPagingOperators( this NameValueCollection that ) { return that.AsEnumerable() .Where( @param => @param.Key != OdataParameters.Skip && @param.Key != OdataParameters.Top ) .ToNameValueCollection(); }код:
using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; public static class NamedValueCollectionExtensions { public static IEnumerable<KeyValuePair<string, string[]>> AsEnumerable( this NameValueCollection that ) { return that .Cast<string>() // doesn't implement IEnumerable<T>, but does implement IEnumerable .Select( ( item, index ) => // enable indexing by integer rather than string new KeyValuePair<string, string[]>( item, that.GetValues( index ) ) ); // if you use the indexer or GetValue it flattens multiple values for a key, Joining them with a ',' which we don't want } public static IEnumerable<KeyValuePair<string, string>> AsKeyValuePairs( this IEnumerable<KeyValuePair<string, string[]>> that ) { return that .SelectMany( item => item.Value.Select( value => new KeyValuePair<string, string>( item.Key, value ) ) ); } public static NameValueCollection ToNameValueCollection( this IEnumerable<KeyValuePair<string, string[]>> that ) { return that.AsKeyValuePairs().ToNameValueCollection(); } public static NameValueCollection ToNameValueCollection( this IEnumerable<KeyValuePair<string, string>> that ) { var result = new NameValueCollection(); foreach ( KeyValuePair<string, string> item in that ) result.Add( item.Key, item.Value ); return result; } }
Я действительно не понимаю, зачем кому-то нужно добавлять метод расширения.
Вот несколько различных способов сделать это в VB.NET. он включает в себя 4 различных промежуточных форм IEnumerable: массив, Кортеж, анонимный и KeyValuePair. Для эквивалента C# перейдите в конвертер.telerik dot com и конвертировать его.Dim nvc As New NameValueCollection() From {{"E", "55"}, {"A", "11"}, {"D", "44"}, {"C", "33"}, {"G", "66"}, {"B", "22"}} Dim dictStrings As Dictionary(Of String, String) = nvc.Cast(Of String).ToDictionary(Function(key) key, Function(key) nvc(key)) Dim Ints2Chars__ As Dictionary(Of Integer, Char) = nvc.Cast(Of Object).ToDictionary(Function(key) CInt(nvc(CStr(key))), Function(key) CChar(key)) Dim arrEnumerable__ = From x In nvc.Cast(Of String) Select {x, nvc(x)} Dim tupleEnumerable = From x In nvc.Cast(Of String) Select Tuple.Create(x, nvc(x)) Dim anonEnumerable_ = From X In nvc.Cast(Of String) Select New With {X, .Y = nvc(X)} Dim kvpEnumerable__ = From x In nvc.Cast(Of String) Select New KeyValuePair(Of String, String)(x, nvc(x)) Dim anonQuery = From anon In anonEnumerable_ Let n = CInt(anon.Y) Order By n Where n > 30 Select New With {.num = n, .val = anon.X} Dim dictQuery = anonQuery.ToDictionary(Of Integer, String)(Function(o) o.num, Function(o) o.val) Dim dictArray_ = arrEnumerable__.ToDictionary(Function(x) x(0), Function(x) x(1)) Dim dictTuples = tupleEnumerable.ToDictionary(Function(tuple) tuple.Item1, Function(tuple) tuple.Item2) Dim dictAnon__ = anonEnumerable_.ToDictionary(Function(anon) anon.X, Function(anon) anon.Y) Dim dictKVPrs_ = kvpEnumerable__.ToDictionary(Function(kvp) kvp.Key, Function(kvp) kvp.Value)
Comments