C#:cómo verificar si un tipo tiene un constructor predeterminado

C#:cómo verificar si un tipo tiene un constructor predeterminado

Un constructor predeterminado es un constructor que no tiene parámetros.

Por lo tanto, para verificar si un tipo tiene un constructor predeterminado, puede usar la reflexión para recorrer los constructores y ver si hay alguno sin parámetros, como este:

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

En este artículo, mostraré un ejemplo de tipos de carga que implementan una interfaz específica, IPlugin, y solo los carga si tienen un constructor predeterminado.

Interfaz de complemento

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

Cargar los tipos de IPlugin con constructores predeterminados

El siguiente código obtiene todos los tipos de IPlugin en el ensamblado actual, luego crea una instancia si el tipo tiene un constructor predeterminado.

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)

Nota:está creando una tabla de enrutamiento basada en lo que el complemento dice que puede manejar.

Tres escenarios de constructor predeterminados

Complemento FileSystemDataHandler:tiene un constructor predeterminado generado por el compilador

Cuando no declara un constructor, el compilador crea automáticamente un constructor predeterminado para usted. Cuando ejecute el código, cargará este complemento porque tiene un constructor predeterminado.

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

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

Complemento HttpDataHandler:tiene un constructor predeterminado declarado definido por el usuario

En esta clase, declaré un constructor que no tiene parámetros; por lo tanto, es un constructor predeterminado y este complemento se cargará cuando ejecute el código.

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)

Complemento SqlDataHandler:sin constructor predeterminado

El siguiente complemento tiene un constructor con parámetros, lo que significa que no tiene un constructor predeterminado. Debido a que no tiene un constructor predeterminado, no se cargará.

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)

Resultados

La ejecución del código da como resultado el siguiente resultado. Como puede ver, no carga SqlDataHandler (porque no tiene un constructor predeterminado, por lo tanto, se filtra).