Create an instance of a class from a string
Asked Answered
M

8

275

Is there a way to create an instance of a class based on the fact I know the name of the class at runtime. Basically I would have the name of the class in a string.

Manno answered 21/10, 2008 at 23:38 Comment(1)
You seem to have described the solution you want to implement, but not the problem you're trying to solve. Perhaps you are trying to do something with extensibility, in which case I suggest you check out the Managed Extensibility Framework.Silk
A
182

Take a look at the Activator.CreateInstance method.

Armorial answered 21/10, 2008 at 23:39 Comment(5)
Related with great examples: #493990Middleweight
Also this post will be relevant as well, as your type needs to be found: #1825647Dareece
Examples: #7598588Glomeration
For example: var driver = (OpenQA.Selenium.IWebDriver)Activator.CreateInstance("WebDriver", "OpenQA.Selenium.Firefox.FirefoxDriver").Unwrap();Stigma
Important note here: .Unwrap() to get past the remoting handle so you can actually do the casts. @Endy - ThanksCounterrevolution
I
127

Its pretty simple. Assume that your classname is Car and the namespace is Vehicles, then pass the parameter as Vehicles.Car which returns object of type Car. Like this you can create any instance of any class dynamically.

public object GetInstance(string strFullyQualifiedName)
{         
     Type t = Type.GetType(strFullyQualifiedName); 
     return  Activator.CreateInstance(t);         
}

If your Fully Qualified Name(ie, Vehicles.Car in this case) is in another assembly, the Type.GetType will be null. In such cases, you have loop through all assemblies and find the Type. For that you can use the below code

public object GetInstance(string strFullyQualifiedName)
{
     Type type = Type.GetType(strFullyQualifiedName);
     if (type != null)
         return Activator.CreateInstance(type);
     foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
     {
         type = asm.GetType(strFullyQualifiedName);
         if (type != null)
             return Activator.CreateInstance(type);
     }
     return null;
 }

Now if you want to call a parameterized constructor do the following

Activator.CreateInstance(t,17); // Incase you are calling a constructor of int type

instead of

Activator.CreateInstance(t);
Immingle answered 25/11, 2014 at 5:19 Comment(7)
How to use it without casting and how to do the cast from the given string??Popele
@Popele - in order to use a class instance you will need to have some knowledge of what it is going to do - otherwise you won't be able to use it. The most common use case for this would be casting to some interface which give you a predefined contract. (This holds unless you're using dynamic code - see https://mcmap.net/q/108024/-what-is-the-39-dynamic-39-type-in-c-4-0-used-for)Selfrespect
Don't encode the type of the variable in it's name., e.g: there is no need to prefix strFullyQualifiedName with str, fullyQualifiedName will do the job.Manoeuvre
The keyword str is used as a part of naming convention for variables. Certain organizations and projects insist to follow this, hence I used. If you would have worked in certain oraganizations/projects, you will know this. As you said without str also it will do the job :) @MehdiDehghaniImmingle
I know, there is no need to work in any organization to know about naming conventions though, this convention known as Hungarian notation and it's one of the bad and deprecated naming convention out there. specially for C#Manoeuvre
That's fine. Anyhow you will see expected result though using this notation. Its up to the people searching for this answer whether to use str or not. Thanks for the note bro @MehdiDehghaniImmingle
@MehdiDehghani The real sad point is that 90% of people did not realised the essence of Hungarian notation: It's not for variable's data types, it's for variable's usage types. Systems Hungarian is depricated, Apps Hungarian is still useful.Bollay
U
58

I've used this method successfully:

System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(string className)

You'll need to cast the returned object to your desired object type.

Unsling answered 21/10, 2008 at 23:43 Comment(6)
I'm trying to imagine a scenario where creating the object via class name and then casting it as that type would make any sense at all.Introvert
I see what you mean. It seems redundant. If you know the class name, why do you need the dynamic string? One situation could be that your casting to a base class and the string represents descendants of that base class.Unsling
If base class is known, you can use the base class or an interface of it as the argument to pass descendants without reflection.Wive
Useful scenario: you only need the serialization interfaces, or any other quite common interface. You won't cast it to the class, but at least to something more than an objectRiha
Xaml on click to a new navigation page is the perfect example, I can think of many more.Sunrise
How to do the cast from the given string??Popele
M
27

Probably my question should have been more specific. I actually know a base class for the string so solved it by:

ReportClass report = (ReportClass)Activator.CreateInstance(Type.GetType(reportClass));

The Activator.CreateInstance class has various methods to achieve the same thing in different ways. I could have cast it to an object but the above is of the most use to my situation.

Manno answered 22/10, 2008 at 0:38 Comment(2)
Instead of responding in the question section, I would suggest you edit your question and note the changes. You will get more/better answers for doing it.Improvident
Thanks for posting the specific line of code that worked for you. Sorting through all the CreateInstance overloads and different ways to generate Types was taking me a lot of time, which you saved me.Eade
I
8

To create an instance of a class from another project in the solution, you can get the assembly indicated by the name of any class (for example BaseEntity) and create a new instance:

  var newClass = System.Reflection.Assembly.GetAssembly(typeof(BaseEntity)).CreateInstance("MyProject.Entities.User");
Itis answered 19/12, 2018 at 11:50 Comment(1)
While others answer the question, this is a great answer that deals with ensuring you have the appropriate assembly if you know a sibling class in my case. BravoTheron
I
4

I know I'm late to the game... but the solution you're looking for might be the combination of the above, and using an interface to define your objects publicly accessible aspects.

Then, if all of your classes that would be generated this way implement that interface, you can just cast as the interface type and work with the resulting object.

Incomputable answered 16/11, 2012 at 22:15 Comment(0)
P
3

For instance, if you store values of various types in a database field (stored as string) and have another field with the type name (i.e., String, bool, int, MyClass), then from that field data, you could, conceivably, create a class of any type using the above code, and populate it with the value from the first field. This of course depends on the type you are storing having a method to parse strings into the correct type. I've used this many times to store user preference settings in a database.

Plenipotent answered 23/9, 2010 at 18:33 Comment(0)
J
-14
ReportClass report = (ReportClass)Activator.CreateInstance(Type.GetType(reportClass));

why do u want to write a code like this? If you have a class 'ReportClass' is available, you can instantiate it directly as shown below.

ReportClass report = new ReportClass();

The code ReportClass report = (ReportClass)Activator.CreateInstance(Type.GetType(reportClass)); is used when you dont have the necessary class available, but you want to instantiate and or or invoke a method dynamically.

I mean it is useful when u know the assembly but while writing the code you dont have the class ReportClass available.

Joshua answered 11/5, 2010 at 9:4 Comment(1)
ReportClass could be the base class or interfaceOutwear

© 2022 - 2024 — McMap. All rights reserved.