C# – How to check if a type has a default constructor

A default constructor is a constructor that doesn’t have parameters.

Therefore, to check if a type has a default constructor, you can use reflection to loop through the constructors and see if there are any with no parameters, like this:

private static bool HasDefaultConstructor(Type type)
{
	return type.GetConstructors().Any(t => t.GetParameters().Count() == 0);
}
Code language: C# (cs)

In this article I’ll show an example of loading types that implement a specific interface and only create an instance of them if they have a default constructor.

Loading the types with default constructors

For this example, I’ll be looking for all classes that implement the following interface called IPlugin:

public interface IPlugin
{
	string HandlesDataFromSource { get; }
	void ProcessData(string data);
}
Code language: C# (cs)

The following code loads all types implementing the IPlugin interface. Then it creates an instance of each type that has a default constructor and adds it to a dictionary:

static void Main(string[] args)
{
	var candidateTypes = GetAllTypesThatImplementInterface<IPlugin>();

	Dictionary<string, IPlugin> routingTable = new Dictionary<string, IPlugin>();

	foreach(var type in candidateTypes)
	{
		if(HasDefaultConstructor(type))
		{
			var plugin = (IPlugin)Activator.CreateInstance(type);
			routingTable.Add(plugin.HandlesDataFromSource, plugin);
			Console.WriteLine($"Created type {type.Name}");

		}
		else
		{
			Console.WriteLine($"Not creating type {type.Name} - it doesn't have a default constructor");
		}
	}
}

private static bool HasDefaultConstructor(Type type)
{
	return type.GetConstructors().Any(t => t.GetParameters().Count() == 0);
}

private static IEnumerable<Type> GetAllTypesThatImplementInterface<T>()
{
	return System.Reflection.Assembly.GetExecutingAssembly()
	  .GetTypes()
	  .Where(type => typeof(T).IsAssignableFrom(type) && !type.IsInterface);
}
Code language: C# (cs)

Note: It’s using the dictionary as a routing table based on what the plugin says it can handle.

Three default constructor scenarios

FileSystemDataHandler plugin – has compiler-generated default constructor

When you don’t declare a constructor, the compiler automatically creates a default constructor for you. When I run the code, it’ll load this plugin because it has a default constructor.

public class FileSystemDataHandler : IPlugin
{
	public string HandlesDataFromSource => "FileSys";

	public void ProcessData(string data)
	{
		//process data
	}
}
Code language: C# (cs)

HttpDataHandler plugin – has user-defined declared default constructor

In this class I declared a constructor that has no parameters – therefore it’s a default constructor, and this plugin will be loaded when I run the code.

public class HttpDataHandler : IPlugin
{
	public string HandlesDataFromSource => "Http";

	public void ProcessData(string data)
	{
		//process data
	}
	private HashSet<string> wordFilterSet;
	public HttpDataHandler()
	{
		var wordFilterList = ConfigurationManager.AppSettings["wordFilter"].Split(',');
		wordFilterSet = new HashSet<string>(wordFilterList);
	}
}
Code language: C# (cs)

This example is parsing a CSV string from a config file.

SqlDataHandler plugin – no default constructor

The following plugin has a constructor with parameters, which means it doesn’t have a default constructor. Because it doesn’t have a default constructor, it will not be loaded.

public class SqlDataHandler : IPlugin
{
	private ConnectionStringSettings ConnectionStringSettings;

	public SqlDataHandler(ConnectionStringSettings connectionStringSetting)
	{
		ConnectionStringSettings = connectionStringSetting;
	}

	public string HandlesDataFromSource => "Sql";

	public void ProcessData(string data)
	{
		//process data
	}
}
Code language: C# (cs)

Results

Running the code results in the following output. As you can see it doesn’t load SqlDataHandler (because it doesn’t have a default constructor, therefore it’s filtered out).

Not creating type SqlDataHandler - it doesn't have a default constructor
Created type FileSystemDataHandler
Created type HttpDataHandlerCode language: plaintext (plaintext)

Leave a Comment