Use a list of delegates
-------------

I'm going to introduce a few programming concepts here so bear with the long answer.

First, you need somewhere to store your results all together. A DTO class perhaps; would look like this example. I added a `ToString()` override so you can see the contents in the debug pane instead of just the class name:

	public enum Gender
	{
		Male, Female
	}
	
	
	public class DocumentMetadata
	{
		public DateTime DateOfBirth { get; set; }
		public Gender Gender { get; set; }
		public string RefNum { get; set; }
		
		public override string ToString()
		{
			return string.Format("DocumentMetadata: DOB={0:yyyy-MM-dd}, Gender={1}, RefNum={2}", DateOfBirth, Gender, RefNum);
		}
	}

Now that we have a DTO, we can reason about how to parse the lines. Ideally, we'd want a series of idempotent functions that you can unit test easily. And to iterate over them, it would be helpful if they were similar in some way. So we define a delegate:

	public delegate bool Parser(string line, DocumentMetadata dto);

So we can write a parser method sort of like this:

	protected bool ParseDateOfBirth(string line, DocumentMetadata dto)
	{
		if (!line.StartsWith("DOB:")) return false;
		dto.DateOfBirth = DateTime.Parse(line.Substring(4));
		return true;
	}

Now here are a few more things to worry about:

1. We want our parser methods contained in a single unit of code, e.g. a class.
2. We want the class to be injectable, e.g. in case you need to have more than one kind of parser in the future, and so you can stub it out for unit tests.
3. We want the logic for iterating parsers to be common.

So first define an interface:

	public interface IDocumentParser
	{
		DocumentMetadata Parse(IEnumerable<string> input);
	}

An abstract base parser:

	public abstract class BaseParser : IDocumentParser
	{
		protected abstract List<Parser> GetParsers();
		
		public virtual DocumentMetadata Parse(IEnumerable<string> input)
		{
			var parsers = this.GetParsers();
			var instance = new DocumentMetadata();
			
			foreach (var line in input)
			{
				foreach (var parser in parsers)
				{
					parser(line, instance);
				}
			}
			return instance;
		}		
	}

Or if we want the Parse function to be a bit more clever (and also count the lines that are successfully parsed):

		public virtual DocumentMetadata Parse(IEnumerable<string> input)
		{
			var parsers = this.GetParsers();
			var instance = new DocumentMetadata();
			
			var successCount = input.Sum( line => parsers.Count( parser => parser(line, instance) ));
												
			Console.WriteLine("{0} lines successfully parsed.", successCount);
	
			return instance;
		}

Now we have a basic framework for parsing documents. All we need is to implement `GetParsers` so that it returns a list of methods that do the work:

	public class DocumentParser : BaseParser
	{
		protected override List<Parser> GetParsers()
		{
			return new List<Parser>
			{
				ParseDateOfBirth,
				ParseGender,
				ParseRefNum
			};
		}
		
		protected bool ParseDateOfBirth(string line, DocumentMetadata dto)
		{
			if (!line.StartsWith("DOB:")) return false;
			dto.DateOfBirth = DateTime.Parse(line.Substring(4));
			return true;
		}
		
		protected bool ParseGender(string line, DocumentMetadata dto)
		{
			if (!line.StartsWith("Sex:")) return false;
			var s = line.Substring(4,1);
			if (s == "M")
			{
				dto.Gender = Gender.Male;
				return true;
			}
			if (s == "F")
			{
				dto.Gender = Gender.Female;
				return true;
			}
			return false;
		}
		
		protected virtual bool ParseRefNum(string line, DocumentMetadata dto)
		{
			if (!line.StartsWith("RefNum:")) return false;
			
			dto.RefNum = line.Substring(7);
			return true;
		}
	}

Notice that only the document-specific logic is held in the final implementation. And all it does is supply the delegates via `GetParsers()`. All common logic is in the base class, where it can be reused.

We can now parse a document with a couple lines of code:

 var parser = new DocumentParser();
 var doc = parse.Parse(input);

But we'd like to inject this thing, so let's write it properly:

	public class Application
	{
		protected readonly IDocumentParser _parser; // injected
		
		public Application(IDocumentParser parser)
		{
			_parser = parser;
		}
		
		public void Run()
		{
			var input = new string[]
			{
				"DOB:1/1/2018",
				"Sex:Male",
				"RefNum:1234"
			};
			
			var result = _parser.Parse(input);
			
			Console.WriteLine(result);
		}
	}
						
	public class Program
	{
		public static void Main()
		{
			var application = new Application(new DocumentParser());
			application.Run();
		}
	}

Output:

 3 lines successfully parsed.
 DocumentMetadata: DOB=2018-01-01, Gender=Male, RefNum=1234

[Working example on DotNetFiddle](https://dotnetfiddle.net/nWt5Yi)