Попробуйте использовать ToLookup
вместо ToDictionary
. Поиски естественным образом работают с linq и универсальным кодом, будучи неизменными и предоставляя очень простой API. Кроме того, я бы инкапсулировал синтаксический анализ в структуру EventLogLine
.
В результате код будет выглядеть так:
IEnumerable<string> lines;
ILookup<string, EventLogLine> lookup =
lines.Select(EventLogLine.Parse).ToLookup(evtLine => evtLine.EventName);
Пример потребителя:
if(lookup["HorribleEvent"].Any())
Console.WriteLine("OMG, Horrible!");
foreach(var evt in lookup["FixableEvent"])
FixIt(evt);
var q = from evtName in relevantEventNames
from evt in lookup[evtName]
select MyProjection(evt);
Обратите внимание, что вам не нужно проверять наличие ключей, в отличие от словаря:
if(dictionary.ContainsKey("HorribleEvent")) //&& dictionary["HorribleEvent"].Any() sometimes needed
Console.WriteLine("OMG, Horrible!");
if(dictionary.ContainsKey("FixableEvent"))
foreach(var evt in lookup["FixableEvent"])
FixIt(evt);
var q = from evtName in relevantEventNames.Where(dictionary.ContainsKey)
from evt in dictionary[evtName]
select MyProjection(evt);
Как вы можете заметить, при работе со словарем, содержащим значения IEnumerable, возникает небольшое трение - ILookup - это то, что вам нужно!
Наконец, модифицированный EventLogLine
:
public struct EventLogLine {
public string EventName { get; private set; }
public string Message { get; private set; }
public DateTime Date { get; private set; }
public static EventLogLine Parse(string line) {
var splitline = line.Split('|');
if(splitline.Length != 3) throw new ArgumentException("Invalid event log line");
return new EventLogLine {
EventName = splitline[0],
Message = splitline[1],
Date = DateTime.Parse(splitline[2]),
};
}
}