Если у вас есть контроль над кодом, генерирующим ваши URL, то я бы рекомендовал вам изменить его, чтобы ввести разделитель между вашими парами ключ-значение. В сложившейся ситуации трудно определить, где заканчивается значение и начинается следующая клавиша.
Пошаговое решение проблемы.
Сначала извлеките строку запроса из вашего URL (который, как я предполагаю, будет находиться в urlString
):
Uri uri = new Uri(urlString);
NameValueCollection outer = HttpUtility.ParseQueryString(uri.Query);
Из-за способа кодирования строка запроса технически содержит только одну пару ключ-значение с ключом k
. Остальные ваши пары ключ-значение кодируются в значении k
. Таким образом, мы получим это значение и расшифруем его:
string k = outer["k"];
string decoded = HttpUtility.UrlDecode(k);
Следующая часть самая хитрая: извлечение ключей и значений. Мы будем использовать регулярные выражения для сопоставления этих:
var matches = Regex.Matches(decoded, @"(?<key>\w+):(?<value>.*?)(?= \w+:|$)");
Предположим, что ваши ключи состоят только из буквенных символов (букв, цифр и подчеркиваний); таким образом, они будут соответствовать (?<key>\w+)
. За каждой клавишей следует символ :
. Далее значения могут состоять из любой последовательности символов, (?<value>.*?)
. Однако за ними должен следовать либо другой ключ \w+:
, либо конец строки $
; таким образом, мы будем использовать положительный прогноз для сопоставления любого из них.
Наконец, просто конвертируйте любые совпадения в словарь:
IDictionary<string, string> dictionary = matches.Cast<Match>().ToDictionary(
m => m.Groups["key"].Value,
m => m.Groups["value"].Value);
В совокупности это даст вам:
Uri uri = new Uri(urlString);
NameValueCollection outer = HttpUtility.ParseQueryString(uri.Query);
string k = outer["k"];
string decoded = HttpUtility.UrlDecode(k);
var matches = Regex.Matches(decoded, @"(?<key>\w+):(?<value>.*?)(?= \w+:|$)");
IDictionary<string, string> dictionary = matches.Cast<Match>().ToDictionary(
m => m.Groups["key"].Value,
m => m.Groups["value"].Value);