Casey Crookston Casey Crookston - 2 months ago 5
ASP.NET (C#) Question

Pass type as Type instead of string paramater

I would like to convert this (which is error prone)....

public static void GenerateReport(string report)
{
switch (report)
{
case "ReportA":
// do stuff
break;
case "ReportB":
// do stuff
break;
case "ReportC":
// do stuff
break;
}
}


To this....

public static void GenerateReport<T>()
{
switch (T) // BUT.... how do I handle this?
{
case ReportA:
// do stuff
break;
case ReportB:
// do stuff
break;
case ReportC:
// do stuff
break;
}
}


I have seen a LOT of questions that ask almost the same thing, but none of them have led me to an answer. Like this one, but for me, the solution provided in that thread flat out doesn't work. It throws multiple syntax errors when I try to compile. the solution there says:

switch typeof(T) {
//
}

Answer

Whenever you have if/switch statements where the code will execute differently depending on the input but produce generic output like what you have in your question it is usually a sign that you need to look into doing some refactoring.

In this case the best option would be to use an interface based design and move the logic for executing the various reports into their own types. This will allow you to better manage additional reports on an as needed basis without having to touch the existing code.

public interface IReporter {
    void GenerateReport();
}

public class ReporterA : IReporter {
    public void GenerateReport() { /* execute report */} 
}
public class ReporterB : IReporter {
    public void GenerateReport() { /* execute report */} 
}
public class ReporterC : IReporter {
    public void GenerateReport() { /* execute report */} 
}

// The responsibilty of the factory is only to create the correct reporter based on the request
public class ReporterFactory{
    public IReporter CreateReporter(string input){
        /*  the logic here can vary, you can get creative with Attributes 
            and name each report type and use reflection to create the 
            correct report type. You can also use an Enum and use that as an attribute value over
            each Reporter type. There are many ways to handle it.
        */
    }
}

/* your refactored method */
public static void GenerateReport(string report)
{
    /* again, creation pattern could be based on something other than a string. It depends on how you want to differentiate your reporters*/
    var reporter = new ReporterFactory().CreateReporter(report);
    reporter.GenerateReport();
}