C #: création d'une instance d'un type basé sur une valeur Enum intégrale

c# dapper

Question

J'ai une interface pour implémenter un "formateur de sortie" qui ressemble un peu à ceci:

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; }
}

SomeFormattableEntity est donc conservé dans une base de données via Dapper et sa propriété OutputType est stockée sous forme de valeur entière sous-jacente (c'est-à-dire dans une colonne INT ). Comme vous pouvez le deviner, je veux fournir une instance d'un IFormatOutput pour gérer un SomeFormattableEntity basé sur sa propriété OutputType .

Existe-t-il une manière propre et efficace de gérer ce type de relation? Mes idées jusqu'à présent incluent une usine avec des entrailles potentiellement composé de:

  1. déclaration horrible du grand-père
  2. un tableau mappant la valeur enum à un type
  3. nom de membre enum de mappage magique basé sur la réflexion comme chaîne vers le type de classe ailleurs
  4. un mécanisme de mappage impliquant des attributs

Je me rends compte qu'il n'est pas souhaitable d'exiger une instance d'une chose dont le type est basé sur une valeur, mais il semble difficile d'éviter cela lorsque SQL est impliqué. Fondamentalement, le problème est que plusieurs «choses» qui ont tous des types .NET différents sont stockées dans une seule table. Je continue à courir dans cet idiome et je suis incapable de trouver une solution élégante.

Réponse acceptée

Je choisirais probablement un attribut personnalisé avec une propriété FormatsOutputFor. IFormatOutput ensuite toutes vos implémentations d' IFormatOutput avec l'attribut. par exemple

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

Puis dans votre usine:

// 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>

Vous souhaitez probablement créer un cache interne qui mappe une valeur OutputFormat sur un Type . Ensuite, votre usine peut vérifier que vous avez uniquement un type mappé sur chaque format de sortie et si vous essayez d'obtenir un formateur pour une valeur d'énumération qui n'a pas de classe correspondante, vous n'obtiendrez pas une exception TypeLoadException obscure de la part de l'activateur.

J'espère que cela a du sens ...


Réponse populaire

Que diriez-vous:

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

En supposant que les éléments de votre enum ont le nom exact de vos types?




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi