Instantiate an object with a runtime-determined type
There are several ways you can create an object of a certain type on the fly, one is:
// determine type here
var type = typeof(MyClass);
// create an object of the type
var obj = (MyClass)Activator.CreateInstance(type);
And you'll get an instance of MyClass in obj.
Another way is to use reflection:
// get type information
var type = typeof(MyClass);
// get public constructors
var ctors = type.GetConstructors(BindingFlags.Public);
// invoke the first public constructor with no parameters.
var obj = ctors[0].Invoke(new object[] { });
And from one of ConstructorInfo returned, you can "Invoke()" it with arguments and get back an instance of the class as if you've used a "new" operator.
Instantiate generic class using runtime class of an object
Because of runtime type erasure, the runtime object created by MyClass<X>
and MyClass<Y>
will be identical. The fact that new MyClass<X>().myMethod()
can be called on an X
but not on a Y
is a compile-time fact, not a run-time one. The compile-time question is "can it be called on this variable", not "can it be called on objects with the same result of getClass()
".
You can create factory methods to create generic instances of your class based on the compile-time types of Class
objects, or of the actual objects you wish to use it with:
public class MyClass<T> {
// ...
public static <T> MyClass<T> forClass(Class<T> c) {
return new MyClass<T>();
}
public static <T> MyClass<T> forObject(T object) {
return new MyClass<T>();
}
}
If you want your generic class's method to actually have runtime type checking, that's possible, too. Just store a Class
object for the type in your MyClass
instance, and use its isInstance()
or cast()
method to check the type of the argument to your method. You have to do this manually, because this is not what is usually done for ordinary generic classes, which is because it is usually unnecessary.
How to create/instantiate an object of 'Type'
Activator.CreateInstance
is what you're after.
var tasks = new List<IScheduledTask>();
foreach (Type t in Assembly.GetExecutingAssembly().GetTypes())
{
if (t.IsSubclassOf(typeof(IScheduledTask)))
{
tasks.Add((IScheduledTask)Activator.CreateInstance(t));
}
}
How to instantiate a certain number of objects determined at runtime?
Just use a
List<Person> lstPersons = new List<Person>();
And then add persons to it with:
lstPersons.Add(new Person());
You can then access the persons with
lstPersons[0]
lstPersons[1]
...
Best way to create an instance of run-time determined type
You are looking for Activator.CreateInstance
(there are also other overloads, such as this one that accepts constructor arguments). So you could write
var anotherOneLikeMe = Activator.CreateInstance(this.GetType());
There may be a problem here in that anotherOneLikeMe
is going to be typed as object
, so unless you intend to cast it to a common base class (e.g. BaseClass
in your example) there's not much that you can do with it.
How do I build a Java type object at runtime from a generic type definition and runtime type parameters?
I think I understand your question. You want to serialize a Foo<T>
, and you have the class object of T
at runtime (but it's not fixed at compile time). Therefore, the suggested solution in Gson of creating an anonymous subclass of TypeToken
does not work because that requires that the parameterized type (e.g. Foo<String>
) be hard-coded at compile time, and it does not work if you use something like Foo<T>
.
However, let's look at what the TypeToken
method on the Gson site actually accomplishes. You create an object of an anonymous subclass of TypeToken
, and then ask for its type parameter using its getType()
method. A class's superclass is part of its metadata, and includes the generic parameters of its superclass. So at runtime, it can look at its own inheritance hierarchy, and figure out what type parameter you used for TypeToken
, and then returns a java.lang.reflect.Type
instance for that type (which, if it is parameterized, will be a ParameterizedType
instance). Once you get this Type
instance, you are supposed to pass it as the second argument of the toGson()
.
All we need to do is find another way to create this instance of ParameterizedType
. ParameterizedType
is an interface, but unfortunately the public Java API does not provide any concrete implementations or any way to create a ParameterizedType
dynamically. There appears to be a class called ParameterizedTypeImpl
, in the private Sun APIs and in the Gson code that you can use (e.g. here). You can simply copy the code and rename it into your own class. Then, to create a Type
object representing Foo<String>
at runtime, you can just do something like new ParameterizedTypeImpl(Foo.class, new Type[]{String.class}, null)
(untested)
How to create a new object instance from a Type
The Activator
class within the root System
namespace is pretty powerful.
There are a lot of overloads for passing parameters to the constructor and such. Check out the documentation at:
http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx
or (new path)
https://learn.microsoft.com/en-us/dotnet/api/system.activator.createinstance
Here are some simple examples:
ObjectType instance = (ObjectType)Activator.CreateInstance(objectType);
ObjectType instance = (ObjectType)Activator.CreateInstance("MyAssembly","MyNamespace.ObjectType");
Instantiating derived types in C++
What's the best way to do this?
You can't. If you declare a variable type as Base
, the stack allocation for it will be suitable for holding an instance of Base
but not an instance of a derived type (which might be larger, though even if it is not, you still cannot do what you ask; the runtime type of a variable in C++ is always the same as its declared type). At best, you could slice the derived instance into a Base
-type variable.
The best bet is to use a pointer, optionally wrapped in a shared_ptr
or unique_ptr
to give you similar semantics (i.e. to have the object be automatically destroyed when it goes out of scope, assuming ownership hasn't been transferred).
Base* b = (condition) ? (Base *) new One() : new Two();
auto bptr = shared_ptr<Base>(b);
Note that what this gives you is effectively the same as the Java. The object itself is heap allocated, but the reference to it is stack allocated. Despite the syntax, a reference-type Java variable is essentially equivalent to a pointer in C++.
Can you instantiate a template class at runtime using C#
Yes, you can instantiate a generic class with a type known only at runtime, e.g.:
public class A { }
public class U<T> {
public T X { get; set; }
}
static void Main(string[] args) {
Type a = typeof(A);
Type u = typeof(U<>);
dynamic uOfA = Activator.CreateInstance(u.MakeGenericType(a));
uOfA.X = new A();
Console.WriteLine(uOfA.GetType());
Console.WriteLine(uOfA.X.GetType());
}
However, this snippet uses reflection and dynamic typing, both of which may cause a lot of maintenance problems, so you would be better off using them very carefully or finding a simpler solution.
Related Topics
Signing and Verifying Signatures with Rsa C#
Populate Data Table from Data Reader
How to Protect Resources That May Be Used in a Multi-Threaded or Async Environment
Web API How to Add a Header Parameter for All API in Swagger
Retrieve Credentials from Windows Credentials Store Using C#
Finding All References to a Method with Roslyn
Differencebetween Preservereferenceshandling and Referenceloophandling in JSON.Net
Resizing an Image in ASP.NET Without Losing the Image Quality
Visual Studio Debugging "Quick Watch" Tool and Lambda Expressions
How to Run a .Net Console Application in the Background
Windows.Forms.Timer or System.Threading.Timer
Navigation Property Should Be Virtual - Not Required in Ef Core
Ef Code First: How to Get Random Rows
Super-Simple Example of C# Observer/Observable with Delegates