Creating an instance of a Type C# with Example



Creating an instance of a Type C# with Example

The simplest way is to use the Activator class. 
However, even though Activator performance have been improved since .NET 3.5, using 
Activator.CreateInstance() is bad option sometimes, due to (relatively) low performance: Test 1, Test 2, Test 3... 
With Activator class 
Type type = typeof(BigInteger); 
object result = Activator.CreateInstance(type); //Requires  parameterless  constructor. 
Console.WriteLine(result); //Output: 0 
result = Activator.CreateInstance(type, 123); //Requires a constructor which can receive an 'int' 
compatible argument. 
Console.WriteLine(result); //Output: 123 
You can pass an object array to Activator.CreateInstance if you have more than one parameter. 
// With a constructor such as MyClass(int, int, string) 
Activator.CreateInstance(typeof(MyClass), new object[] { 1, 2, "Hello World" }); 
 

Type type = typeof(someObject); 
var instance = Activator.CreateInstance(type); 
For a generic type 
The MakeGenericType method turns an open generic type (like List<>) into a concrete type (like List) by 
applying type arguments to it. 
// generic List with no parameters 
Type openType = typeof(List<>); 
// To create a List 
Type[] tArgs = { typeof(string) }; 
Type target = openType.MakeGenericType(tArgs); 
// Create an instance - Activator.CreateInstance will call the default constructor. 
// This is equivalent to calling new List(). 
List result = (List)Activator.CreateInstance(target); 
The List<> syntax is not permitted outside of a typeof expression. 
Without Activator class 
Using new keyword (will do for parameterless constructors) 
T GetInstance() where T : new() 
{ 
T instance = new T(); 
return instance; 
} 
Using Invoke method 
// Get the instance of the desired constructor (here it takes a string as a parameter). 
ConstructorInfo c = typeof(T).GetConstructor(new[] { typeof(string) }); 
// Don't forget to check if such constructor exists 
if (c == null) 
throw new InvalidOperationException(string.Format("A constructor for type '{0}' was not 
found.", typeof(T))); 
T instance = (T)c.Invoke(new object[] { "test" }); 
Using Expression trees 
Expression trees represent code in a tree-like data structure, where each node is an expression. As MSDN explains: 
Expression is a sequence of one or more operands and zero or more operators that can be evaluated to a 
single value, object, method, or namespace. Expressions can consist of a literal value, a method 
invocation, an operator and its operands, or a simple name. Simple names can be the name of a variable, 
type member, method parameter, namespace or type. 
public class GenericFactory 
{ 
private readonly Dictionary> _registeredTypes; // dictionary, 
that holds constructor functions. 
private object _locker = new object(); // object for locking dictionary, to guarantee thread 
 

safety 
public GenericFactory() 
{ 
_registeredTypes = new Dictionary>(); 
} 
///  
/// Find and register suitable constructor for type 
///  
///  
/// Key for this constructor 
/// Parameters 
public void Register(TKey key, params Type[] parameters) 
{ 
ConstructorInfo ci = typeof(TType).GetConstructor(BindingFlags.Public | 
BindingFlags.Instance, null, CallingConventions.HasThis, parameters, new ParameterModifier[] { }); 
// Get the instance of ctor. 
if (ci == null) 
throw new InvalidOperationException(string.Format("Constructor for type '{0}' was 
not found.", typeof(TType))); 
Func ctor; 
lock (_locker) 
{ 
if (!_registeredTypes.TryGetValue(key, out ctor)) //  check  if  such  ctor  already 
been registered 
{ 
var pExp = Expression.Parameter(typeof(object[]), "arguments"); // create 
parameter Expression 
var ctorParams = ci.GetParameters(); // get parameter info from constructor 
var argExpressions = new Expression[ctorParams.Length]; // array that will 
contains parameter expessions 
for (var i = 0; i < parameters.Length; i++) 
{ 
var indexedAcccess = Expression.ArrayIndex(pExp, Expression.Constant(i)); 
if (!parameters[i].IsClass && !parameters[i].IsInterface) // check if 
parameter is a value type 
{ 
var localVariable = Expression.Variable(parameters[i], 
"localVariable"); // if so - we should create local variable that will store paraameter value 
var block = Expression.Block(new[] { localVariable }, 
Expression.IfThenElse(Expression.Equal(indexedAcccess, 
Expression.Constant(null)), 
Expression.Assign(localVariable, 
Expression.Default(parameters[i])), 
Expression.Assign(localVariable, 
Expression.Convert(indexedAcccess, parameters[i])) 
), 
localVariable 
); 
argExpressions[i] = block; 
} 
else 
argExpressions[i] = Expression.Convert(indexedAcccess, parameters[i]); 
 

} 
var newExpr = Expression.New(ci, argExpressions); // create expression that 
represents call to specified ctor with the specified arguments. 
_registeredTypes.Add(key, Expression.Lambda(newExpr, new[] { pExp }).Compile() 
as Func); // compile expression to create delegate, and add function to dictionary 
} 
} 
} 
///  
/// Returns instance of registered type by key. 
///  
///  
///  
///  
///  
public TType Create(TKey key, params object[] args) 
{ 
Func foo; 
if (_registeredTypes.TryGetValue(key, out foo)) 
{ 
return (TType)foo(args); 
} 
throw new ArgumentException("No type registered for this key."); 
} 
} 
Could be used like this: 
public class TestClass 
{ 
public TestClass(string parameter) 
{ 
Console.Write(parameter); 
} 
} 
public void TestMethod() 
{ 
var factory = new GenericFactory(); 
factory.Register("key", typeof(string)); 
TestClass newInstance = factory.Create("key", "testParameter"); 
} 
Using FormatterServices.GetUninitializedObject 
T instance = (T)FormatterServices.GetUninitializedObject(typeof(T)); 
In case of using FormatterServices.GetUninitializedObject constructors and field initializers will not be called. It 
is meant to be used in serializers and remoting engines 

0 Comment's

Comment Form

Submit Comment