So, I asked the following question in at http://forums.asp.net/t/1408631.aspx
The problem is, I’ve got 30 methods that all have the same signature, but have different implementations. Mike Banavige (the lead moderator at the forums) suggested I look at the following article on reflection: http://www.csharphelp.com/archives/archive200.html. Turns out, that helped my solve my problem exactly. Rather than go through a lengthy line by line explanation, I’m going to post some of my before and after code. It’s pretty clear what is happening, but I thought it would be nice to show a real example.
Before Code:
private static void AddTemplateCode(string templateNumber, int indent, ICollection<string> newLines,FullMeta fullMetal)
{
int iTemplateNumber = Convert.ToInt32(templateNumber);
var sb = new StringBuilder(indent);
sb.Append(' ', indent);
string indentString = sb.ToString();
// be nice to get rid of this ugly case statement. Using it because I want to have a way to separate
// methods associated with groups of methods. that is, put Template11-15 in a separate file later.
switch (iTemplateNumber)
{
case 11:
{
Template11(newLines, indentString,fullMetal);
break;
}
case 12:
{
Template12(newLines, indentString,fullMetal);
break;
}
case 13:
{
Template13(newLines, indentString, fullMetal);
break;
}
case 14:
<This goes on and on and on and on>
Then, After, following the sample above:
private static void AddTemplateCode(string templateNumber, int indent, ICollection<string> newLines,FullMeta fullMetal)
{
int iTemplateNumber = Convert.ToInt32(templateNumber);
var sb = new StringBuilder(indent);
sb.Append(' ', indent);
string indentString = sb.ToString();
var processTemplate = new ProcessTemplateDynamic();
processTemplate.DoIt(iTemplateNumber, newLines, indentString, fullMetal);
<Then the class with DoIt in it...>
using System;
using System.Collections.Generic;
using System.Reflection;
namespace ThreePLogicAccessCodeGen.Code
{
public class ProcessTemplateDynamic
{
internal void DoIt(int iTemplateNumber, ICollection<string> newLines, string indentString, FullMeta fullMetal)
{
// Template11(newLines, indentString, fullMetal);
string templateMethodName = String.Format("Template{0}", iTemplateNumber);
var userParameters = new object[3];
userParameters[0] = newLines;
userParameters[1] = indentString;
userParameters[2] = fullMetal;
try
{
Type thisType = GetType();
MethodInfo theMethod = thisType.GetMethod(templateMethodName);
// that we have in this class that we don't want called.
if (theMethod == null || (!CheckMethod(theMethod)))
{
throw new ApplicationException(string.Format("[e] Command <{0}> not supported.", templateMethodName));
}
// Invoke the Method!
theMethod.Invoke(this, userParameters);
}
catch (ArgumentNullException e)
{
// This exception is from the user entering in a null string on the command line
throw new ApplicationException("[e] Please enter in a non-null string. (" + e.Message + ")");
}
catch (TargetParameterCountException e)
{
// This exception is thrown when the method is not passed the right number of parameters
throw new ApplicationException(string.Format("[e] Command <{0}> requires parameters. ({1})",
templateMethodName, e.Message));
}
catch (Exception e)
{
// All other exceptions!
throw new ApplicationException(string.Format("[e] General Exception:n{0}", e));
}
}
Well, looking at it, seems maybe the Case statement is better, but the nice thing now is that each time I add a new template, I don’t have to make another case statement. That combined with it’s easier to make typos when you have a case statement so I’m sticking with my new solution here.
Hope this Helps!