One may not always know the Type
of an object at compile-time, but may need to create an instance of the Type
.
How do you get a new objec
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 strNamesapace)
{
Type t = Type.GetType(strNamesapace);
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;
}
And you can get the instance by calling the above method.
object objClassInstance = GetInstance("Vehicles.Car");
If you want to use the default constructor then the solution using System.Activator
presented earlier is probably the most convenient. However, if the type lacks a default constructor or you have to use a non-default one, then an option is to use reflection or System.ComponentModel.TypeDescriptor
. In case of reflection, it is enough to know just the type name (with its namespace).
Example using reflection:
ObjectType instance =
(ObjectType)System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(
typeName: objectType.FulName, // string including namespace of the type
ignoreCase: false,
bindingAttr: BindingFlags.Default,
binder: null, // use default binder
args: new object[] { args, to, constructor },
culture: null, // use CultureInfo from current thread
activationAttributes: null
);
Example using TypeDescriptor
:
ObjectType instance =
(ObjectType)System.ComponentModel.TypeDescriptor.CreateInstance(
provider: null, // use standard type description provider, which uses reflection
objectType: objectType,
argTypes: new Type[] { types, of, args },
args: new object[] { args, to, constructor }
);
If this is for something that will be called a lot in an application instance, it's a lot faster to compile and cache dynamic code instead of using the activator or ConstructorInfo.Invoke()
. Two easy options for dynamic compilation are compiled Linq Expressions or some simple IL opcodes and DynamicMethod. Either way, the difference is huge when you start getting into tight loops or multiple calls.
I can across this question because I was looking to implement a simple CloneObject method for arbitrary class (with a default constructor)
With generic method you can require that the type implements New().
Public Function CloneObject(Of T As New)(ByVal src As T) As T
Dim result As T = Nothing
Dim cloneable = TryCast(src, ICloneable)
If cloneable IsNot Nothing Then
result = cloneable.Clone()
Else
result = New T
CopySimpleProperties(src, result, Nothing, "clone")
End If
Return result
End Function
With non-generic assume the type has a default constructor and catch an exception if it doesn't.
Public Function CloneObject(ByVal src As Object) As Object
Dim result As Object = Nothing
Dim cloneable As ICloneable
Try
cloneable = TryCast(src, ICloneable)
If cloneable IsNot Nothing Then
result = cloneable.Clone()
Else
result = Activator.CreateInstance(src.GetType())
CopySimpleProperties(src, result, Nothing, "clone")
End If
Catch ex As Exception
Trace.WriteLine("!!! CloneObject(): " & ex.Message)
End Try
Return result
End Function
Given this problem the Activator will work when there is a parameterless ctor. If this is a constraint consider using
System.Runtime.Serialization.FormatterServices.GetSafeUninitializedObject()
public AbstractType New
{
get
{
return (AbstractType) Activator.CreateInstance(GetType());
}
}