Ответ 1
Используйте Dictionary<Char, YourDelegate>
, чтобы указать, как должен обрабатываться символ. Вызовите DefaultHandler
, если символьный ключ не существует в словаре.
Добавьте метод Add(char key, YourDelegate handler)
, позволяющий любому обрабатывать определенный символ.
Update
Лучше работать с интерфейсами:
/// <summary>
/// Let anyone implement this interface.
/// </summary>
public interface IMyHandler
{
void Process(IProcessContext context, string line);
}
/// <summary>
/// Context information
/// </summary>
public interface IProcessContext
{
}
// Actual parser
public class Parser
{
private Dictionary<char, IMyHandler> _handlers = new Dictionary<char, IMyHandler>();
private IMyHandler _defaultHandler;
public void Add(char controlCharacter, IMyHandler handler)
{
_handlers.Add(controlCharacter, handler);
}
private void Parse(TextReader reader)
{
StringBuilder scope = new StringBuilder();
IProcessContext context = null; // create your context here.
string line = reader.ReadLine();
while (line != null)
{
IMyHandler handler = null;
if (!_handlers.TryGetValue(line[0], out handler))
handler = _defaultHandler;
handler.Process(context, line);
line = reader.ReadLine();
}
}
}
Обратите внимание, что вместо этого я передаю TextReader
. Это дает гораздо большую гибкость, поскольку источником может быть что угодно: от простой строки до сложного потока.
Обновление 2
Я также разбил бы обработку !
аналогичным образом. т.е. создать класс, который обрабатывает IMyHandler:
public interface ICommandHandler
{
void Handle(ICommandContext context, string commandName, string[] arguments);
}
public class CommandService : IMyHandler
{
public void Add(string commandName, ICommandHandler handler)
{
}
public void Handle(IProcessContext context, string line)
{
// first word on the line is the command, all other words are arguments.
// split the string properly
// then find the corrext command handler and invoke it.
// take the result and add it to the `IProcessContext`
}
}
Это дает большую гибкость как для обработки фактического протокола, так и для добавления дополнительных команд. вам не нужно ничего менять, чтобы добавить больше функциональности. Таким образом, решение является правильным в отношении Open/Closed и некоторых других принципов SOLID.