Tengo un proyecto C # para ProjectEuler si lo sabes.

Para eso uso una clase abstracta, llamémosla 'X'

public abstract class X {
protected abstract void SomeFunction()
}

Hay más de 600 problemas para resolver en este proyecto. Para cada problema, creo una clase que hereda de X. El nombre de la clase siempre es 'Baseclassname' seguido de un número

Exampel:

public class X2 : X {
public override void SomeFunction()
}

Durante el tiempo de ejecución, elijo a través de la consola ingresar un problema al ingresar un número entero válido. Este número entero entra en un interruptor y crea el problema correspondiente y ejecuta alguna función si '_problema' no es igual a nulo.

X _problem = null;
int someInput; //any valid input readin via Console
switch(someInput)
{
case 1:
_problem = new X1();
break;
case 2:
_problem = new X2();
break;
.
.
.
case 610:
_problem = new X610();
break;
}
_promblem?.someFunction();

Entonces, mi pregunta a la comunidad es cómo evitar un caso de cambio con más de 600 casos. ¿Hay una mejor solución para hacer esto?

Espero que esta pregunta esté bien escrita porque es la primera. :)

Editar: alguna matriz de pares 'clave, valor' solo sería ideal si todos los pares existentes se agregan automáticamente durante la compilación.

1
Griizz 12 ene. 2018 a las 21:01

3 respuestas

La mejor respuesta

Pruebe la reflexión de la siguiente manera;

X _problem = null;
int someInput; //any valid input readin via Console

try
{

_problem = Assembly.GetExecutingAssembly().CreateInstance($«X{someInput}») as X
}
catch{}
_promblem?.someFunction();
1
Surjit SD 12 ene. 2018 a las 18:22

Aquí hay un esqueleto de lo que podría hacer con un menú de opciones para el usuario:

//Get all the types that inherit from 'X'
var types = Assembly.GetExecutingAssembly().GetTypes()
    .Where(t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(typeof(X)))
    .ToList();

Console.WriteLine("Choose a class to run");
var index = 0;
foreach (var type in types)
{
    Console.WriteLine($"{index++}: {type.Name}");
}

Console.Write("Enter number: ");

//Much better to use "TryParse" here and validate the input
index = int.Parse(Console.ReadLine());

var instance = (X)Activator.CreateInstance(types[index]);

instance.SomeFunction();

Tenga en cuenta que deberá cambiar el nivel de protección a public para que esto funcione.

1
DavidG 12 ene. 2018 a las 18:27

Si los nombres están bien formados (es decir, puede generar el nombre de la clase a partir de la entrada), sería fácil utilizar el método CreateInstance de System.Reflection.Assembly y luego enviarlo a su tipo abstracto y llamar al miembro base.

-1
SoronelHaetir 12 ene. 2018 a las 18:16