C #: crea una instancia de un tipo basado en un valor Enum integral

c# dapper

Pregunta

Tengo una interfaz para implementar un "formateador de salida" que se parece un poco a esto:

public interface IFormatOutput {}
public class HtmlOutputFormatter : IFormatOutput {}
public class TextOutputFormatter : IFormatOutput {}
// etc, etc...

public enum OutputFormat {
    Html,
    Text,
    HappyMeal,
    Excel
}

public class SomeFormattableEntity {
    int Id { get; set; }
    OutputFormat OutputType { get; set; }
}

Así que SomeFormattableEntity se conserva en una base de datos a través de Dapper y su propiedad OutputType se almacena como el valor entero subyacente (es decir, en una columna INT ). Como puede adivinar, deseo proporcionar una instancia de un IFormatOutput para manejar una SomeFormattableEntity función de su propiedad OutputType .

¿Hay alguna manera clara de practicar mejor este tipo de relación? Mis ideas hasta ahora incluyen una fábrica con entrañas que consiste en:

  1. declaración de interruptor feo horrible abuelo
  2. una matriz mapeando el valor enum a un Tipo
  3. mapeo mágico basado en la reflexión nombre de miembro enum como cadena a tipo de clase en otra parte
  4. algunos mecanismos de mapeo que involucran atributos

Me doy cuenta de que no es deseable requerir una instancia de una cosa cuyo tipo se basa en un valor, pero parece difícil evitar esto cuando se trata de SQL. Básicamente, el problema es que múltiples "cosas" que tienen diferentes tipos de .NET se almacenan en una sola tabla. Sigo encontrándome con este idioma y no puedo encontrar una solución elegante para él.

Respuesta aceptada

Probablemente vaya por un atributo personalizado con una propiedad FormatsOutputFor. Luego decore todas sus implementaciones de IFormatOutput con el atributo. p.ej

[YourAttribute(OutputFormat.Html)]
public class HtmlOutputFormatter : IFormatOutput {}

Luego en tu fábrica:

// get all your formatters
var formatters = AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany(s => s.GetTypes())
    .Where(p => Attribute.IsDefined(p, typeof(YourAttribute)));

// Now go through each formatter and use the attribute to figure out which
// output format it's for. Add these to some static IDictionary<OutputFormat, Type>

Probablemente desee construir algún caché interno que OutputFormat un valor OutputFormat a un Type . Entonces su fábrica puede verificar que solo tiene un tipo asignado a cada formato de salida y si intenta obtener un formateador para un valor enum que no tiene una clase correspondiente, entonces no obtendrá una TypeLoadException oscura del activador.

Espero que tenga sentido ...


Respuesta popular

Qué tal si:

OutputFormat format = OutputFormat.Excel;
object obj = Activator.CreateInstance("myAssemblyName", format.ToString());

¿Asumiendo que los elementos de tu enumeración tienen el nombre exacto de tus tipos?



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué