Creating instance of type without default constructor in C# using reflection

C#ReflectionInstantiationDefault Constructor

C# Problem Overview


Take the following class as an example:

class Sometype
{
    int someValue;

    public Sometype(int someValue)
    {
        this.someValue = someValue;
    }
}

I then want to create an instance of this type using reflection:

Type t = typeof(Sometype);
object o = Activator.CreateInstance(t);

Normally this will work, however because SomeType has not defined a parameterless constructor, the call to Activator.CreateInstance will throw an exception of type MissingMethodException with the message "No parameterless constructor defined for this object." Is there an alternative way to still create an instance of this type? It'd be kinda sucky to add parameterless constructors to all my classes.

C# Solutions


Solution 1 - C#

I originally posted this answer here, but here is a reprint since this isn't the exact same question but has the same answer:

FormatterServices.GetUninitializedObject() will create an instance without calling a constructor. I found this class by using Reflector and digging through some of the core .Net serialization classes.

I tested it using the sample code below and it looks like it works great:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Runtime.Serialization;

namespace NoConstructorThingy
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass myClass = (MyClass)FormatterServices.GetUninitializedObject(typeof(MyClass)); //does not call ctor
            myClass.One = 1;
            Console.WriteLine(myClass.One); //write "1"
            Console.ReadKey();
        }
    }

    public class MyClass
    {
        public MyClass()
        {
            Console.WriteLine("MyClass ctor called.");
        }

        public int One
        {
            get;
            set;
        }
    }
}

Solution 2 - C#

Use this overload of the CreateInstance method:

public static Object CreateInstance(
    Type type,
    params Object[] args
)

> Creates an instance of the specified > type using the constructor that best > matches the specified parameters.

See: http://msdn.microsoft.com/en-us/library/wcxyzt4d.aspx

Solution 3 - C#

When I benchmarked performance of (T)FormatterServices.GetUninitializedObject(typeof(T)) it was slower. At the same time compiled expressions would give you great speed improvements though they work only for types with default constructor. I took a hybrid approach:

public static class New<T>
{
    public static readonly Func<T> Instance = Creator();
    
    static Func<T> Creator()
    {
        Type t = typeof(T);
        if (t == typeof(string))
            return Expression.Lambda<Func<T>>(Expression.Constant(string.Empty)).Compile();

        if (t.HasDefaultConstructor())
            return Expression.Lambda<Func<T>>(Expression.New(t)).Compile();

        return () => (T)FormatterServices.GetUninitializedObject(t);
    }
}

public static bool HasDefaultConstructor(this Type t)
{
    return t.IsValueType || t.GetConstructor(Type.EmptyTypes) != null;
}

This means the create expression is effectively cached and incurs penalty only the first time the type is loaded. Will handle value types too in an efficient manner.

Call it:

MyType me = New<MyType>.Instance();

Note that (T)FormatterServices.GetUninitializedObject(t) will fail for string. Hence special handling for string is in place to return empty string.

Solution 4 - C#

Good answers but unusable on the dot net compact framework. Here is a solution that will work on CF.Net...

class Test
{
    int _myInt;

    public Test(int myInt)
    {
        _myInt = myInt;
    }

    public override string ToString()
    {
        return "My int = " + _myInt.ToString();
    }
}

class Program
{
    static void Main(string[] args)
    {
        var ctor = typeof(Test).GetConstructor(new Type[] { typeof(int) });
        var obj = ctor.Invoke(new object[] { 10 });
        Console.WriteLine(obj);
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAistinaView Question on Stackoverflow
Solution 1 - C#Jason JacksonView Answer on Stackoverflow
Solution 2 - C#NickView Answer on Stackoverflow
Solution 3 - C#nawfalView Answer on Stackoverflow
Solution 4 - C#AutodidactView Answer on Stackoverflow