12

Within a windows app, using C#, I have a reporting module that will be reliant upon classes to populate the reports. However there will be many reports and I do not want to have to code for each one.

The flow will be as such: Within the report editor, the report will be assigned a class (i.e. "Applications") as a string. When the user selected the report to run, the code will acquire the data from a SQL query. The code will take the data and find out which class to place the data into. Then the report will take the class and populate the report with the data from the class.

Here is my dilemna, how do I make the code dynamic so that the code will convert the assigned class into the proper Class Object?

Example in mind:

gVar = Report;
(gVar.ReportClass)oClass = new gVar.ReportClass;
3
  • Thanks Anthony I forgot to put that last part into code tags
    – mattgcon
    Commented Feb 2, 2011 at 16:00
  • Im not the same person who posted that question, I didn't know how to properly word my question so that didn't pop up
    – mattgcon
    Commented Feb 2, 2011 at 16:03
  • Thats not a problem matt. I just added the duplicate so these can be linked. I would check out that question. It should answer your question (if I understand it correctly). Commented Feb 2, 2011 at 16:05

4 Answers 4

14

Use Type.GetType (specifically one of the overloads (e.g., Type.GetType(string)) that takes a string parameter) to load the instance of Type for the appropriate class, and then use Activator.CreateInstance or Type.GetConstructor on that instance of Type to instantiate an instance.

So, something like

Type type = Type.GetType(assemblyQualifiedName);
object instance = Activator.CreateInstance(type);

Note that you must pass the assembly qualified name unless the type is in mscorlib or the currently executing assembly.

Additionally, Activator.CreateInstance assumes the existence of a default constructor. If there is not a default constructor, or you need to pass some parameters to the constructor, you will have to use an overload of Activator.CreateInstance that lets you specify the constructor parameters, or Type.GetConstructor to load the appropriate constructor.

4
  • here is a question though that just popped into my head, when I do instatiate the class from the string, I am guessing there is no way to place the data into the respective properties within the class dynamically. (i.e reportclass.clientname = dt["CLIENTNAME"].ToString())
    – mattgcon
    Commented Feb 2, 2011 at 16:11
  • If you know that your object will have such a property (say because all of the objects that you are dynamically instantiating derive from a common base class or a common interface, you could cast to that base class or interface and then access the property through that base class or interface). So say all of your objects derive from a class named Report and Report has a property named ClientName. Then you could say Report r = (Report)Activator.CreateInstance(type); r.ClientName = dt["CLIENTNAME"].ToString();. Alternatively, you could use reflection to set the property. Make sense?
    – jason
    Commented Feb 2, 2011 at 16:20
  • Hmmmm, thats an issue then because there is not common base class or common interface and from what I remember about reflection I would have to tell it what properties I am looking for by referencing it in a string.
    – mattgcon
    Commented Feb 2, 2011 at 16:25
  • @mattgcon: Yes, that's how you would set a property using reflection. If you have a convention like there is always a property on the object that matches (ignoring case) the value of string being passed to the indexer of dt, then you can easily do this.
    – jason
    Commented Feb 2, 2011 at 16:27
4

You can use reflection to do it. If you give them all some similar base class or interface, you can do something like:

myBaseReport report = (myBaseReport)System.Activator.CreateInstance("MyAssemblyName", myClassStringWithFullNameSpace).Unwrap();

This will go into the assembly named and load the class directly. The class string is the full name of the type in question, so something like MyGlobalNamespace.MyCustomNameSpace.MySpecificType. This will allow you to create the specific type of report and put it into the base class type or interface type.

3
  • Unfortunately, no two report classes are the same, so a base class or interface was not created.
    – mattgcon
    Commented Feb 2, 2011 at 16:08
  • @mattgcon - Then you'll be better of typing as an object when performing this kind of instantiation. And any methods you pass to will need to accept object. Commented Feb 2, 2011 at 16:13
  • @JoelEtherton : I voted up because you mentioned class name WITH FULL NAMESPACE whcih makes it clear to use.
    – Ram
    Commented Jan 4, 2013 at 6:30
2

It's a little unclear exactly what you're asking for here. Based on what I"m reading, though, you have a string that contains a type name and you want to instantiate a class based on that? You can use reflection to do this...

Type type = Type.GetType(strTypeName);
object oClass = Activator.CreateInstance(type);
2

You'll be fine using implicit operators:

That sounds good for your needs, because it allows you to do something like:

Orange orange = new Orange();
Apple apple = (Apple)orange;

Or:

string appleJson = "{ Weight: '2kg' }";
Apple apple = appleJson;

An implicit operator will deserialize that apple-JSON-serialized string into a regular Apple-typed object.

I don't know if this is what you're looking for, and I hope no one will be voting down if this is a C# feature that's available.

EDITED: I misunderstood the question. Thanks to commenters, even who down-voted my answer, because I was wrong.

EDIT 2:

Taking others Activator/Reflection approach - which seems to be the right one for the author of current question -, and reading his other question about "how to fill then the properties of obtained report instance", I want to suggest some solution.

You can define some attribute like "ReportPropertyAttribute" with no properties, default constructor, and inspect with reflection for properties that are marked with suggested attribute.

Or you can define some configuration file or configuration section (regular .NET configuration API), so you can define "known report types" and "which properties are arguments or parameters of some report type".

I hope this is in the line of your needs!

19
  • This is assuming he knows the type already. The way the question reads to me is the type can vary and he won't know the actual type until runtime. This won't work for that. Commented Feb 2, 2011 at 16:08
  • Well, with the fewer info he provided, I tried to think he's in the other situation, because he says "I don't want to repeat the code of converting A to B". Commented Feb 2, 2011 at 16:10
  • I did say " the report will be assigned a class (i.e. "Applications") as a string" and "how do I make the code dynamic so that the code will convert the assigned class into the proper Class Object?"
    – mattgcon
    Commented Feb 2, 2011 at 16:14
  • Right, now I've double-checked your text, and I understood the problem. I believe reflection/activator approach suggested by others is the right way, or maybe, you can use inversion of control. Commented Feb 2, 2011 at 16:15
  • I am going to use activator, however I am confused as to after what do I do to populate the class object with the data since it will be all done at run time
    – mattgcon
    Commented Feb 2, 2011 at 16:16

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.