Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: Dynamically instantiate different classes in the same statement?

Here is a simplified version of what I'm trying to do:

Without having multiple if..else clauses and switch blocks, can I mimic the behavior of Javascript's eval() shudder to instantiate a class in C#?

// Determine report orientation -- Portrait or Landscape
// There are 2 differently styled reports (beyond paper orientation)

string reportType = "Portrait";
GenericReport report;
report = new eval(reportType + "Report()");  // Resolves to PortraitReport()

The need stems from the fact that I have 6 types of Crystal Reports (that do the same thing, but look drastically different) for 50 states. There are 3 styles each, rather than entertain the notion of a giant switch block with nested if..else statements determining which of 900 reports to use, I was hoping for an eval-like solution.

like image 953
C. Griffin Avatar asked Feb 28 '23 05:02

C. Griffin


2 Answers

You could use Activator.CreateInstance("myAssembly", "PortrainReport");. Although the more readable way would be to create a Portrait Factory, which would create the correct type for you.

like image 65
Yuriy Faktorovich Avatar answered Apr 26 '23 03:04

Yuriy Faktorovich


As people specified above, you can use Activator class to create an instance of the class by its text name.

But, there is one more option. When you told about using eval like function in c# i assumed, you not only want to create an instance of the class by its text name, but also fill it with properties from the same string.

For this purpose you need to use deserialization.

Deserialization converts string like representation of the class into its instance and restoring all its properties that was specified in the string.

Xml serialization. Its using XML file for converting into instance. Here is small example:

public class Report1 
{
 public string Orientation {get;set;}
 public string ReportParameter1 {get;set;}
 public string ReportParameter2 {get;set;}
}

Above is the class that you want to instantiate and fill with parameters by string line. Below is XML that can do that:

<?xml version="1.0"?>
<Report1>
  <Orientation>Landscape</Orientation>
  <ReportParameter1>Page1</ReportParameter1>
  <ReportParameter2>Colorado</ReportParameter2>
</Report1>

To create an instance from the file use System.Xml.Serialization.XmlSerializer :

string xml = @"<?xml version=""1.0""?>
                <Report1>
                  <Orientation>Landscape</Orientation>
                  <ReportParameter1>Page1</ReportParameter1>
                  <ReportParameter2>Colorado</ReportParameter2>
                </Report1>";

            ///Create stream for serializer and put there our xml
            MemoryStream  str = new MemoryStream(ASCIIEncoding.ASCII.GetBytes(xml));

            ///Getting type that we are expecting. We are doing it by passing proper namespace and class name string
            Type expectingType = Assembly.GetExecutingAssembly().GetType("ConsoleApplication1.Report1");

            XmlSerializer ser = new XmlSerializer(expectingType);

            ///Deserializing the xml into the object
            object obj = ser.Deserialize(str);

            ///Now we have our report instance initialized
            Report1 report = obj as Report1;

In this way you can prepare appropriate xml as string concatenation. That xml will contain all parameters for your report.

Then, you can convert it into the proper type.

like image 23
Andrey Tagaew Avatar answered Apr 26 '23 04:04

Andrey Tagaew