2010-01-22 21 views
6

J'ai une classe qui analyse les données d'un fichier texte délimité par des virgules. J'ai une énumération pour les champs pour m'aider à analyser les données plus facilement. La classe qui analyse tous les enregistrements contient des variables publiques pour chaque champ, et bien sûr leurs types de variables. J'ai besoin d'obtenir le type de ces variables basé sur l'énumération donnée.C# Obtention du type d'une variable publique basée sur une valeur Enum

public enum DatabaseField : int 
    { 
     NumID1 = 1, 
     NumID2 = 2, 
     NumID3 = 3, 
    }; 

public class DataBaseRecordInfo 
    { 
     public long NumID1 { get; set; } 
     public int NumID2 { get; set; } 
     public short NumID3 { get; set; } 

     public static Type GetType(DatabaseField field) 
     { 
      Type type; 

      switch (field) 
      { 
       case DatabaseField.NumID1: 
        type = typeof(long); 
        break; 
       case DatabaseField.NumID2: 
        type = typeof(int); 
        break; 
       case DatabaseField.NumID3: 
        type = typeof(short); 
        break; 
       default: 
        type = typeof(int); 
        break; 
      } 

      return type; 
     } 
    }; 

NumID1, NumID2, NumID3 sont tous affectés dans mon constructeur. Cependant, je veux obtenir ces types sans jamais créer une instance de DataBaseRecordInfo. En ce moment ma méthode statique ci-dessus fonctionnerait, cependant, si je voulais changer le type de variable, je devrais le changer en 2 endroits. Y at-il un moyen de contourner le fait d'avoir à changer cela dans les deux endroits et de le garder comme une méthode statique?

+0

Je ne comprends pas la question. Pouvez-vous être plus clair? "Cependant, je veux obtenir ces types sans jamais créer une instance de DataBaseRecordInfo" - qu'est-ce que cela signifie? – hackerhasid

+0

Cela signifie que j'ai des scenerios dans lesquels je veux les types de ces variables, mais je ne veux pas instancier cette classe pour saisir les types. – jsmith

Répondre

4

Si le nom doit toujours correspondre exactement, vous pouvez le faire en utilisant la réflexion.

return typeof(DataBaseRecordInfo) 
    .GetProperty(field.ToString(), BindingFlags.Public | BindingFlags.Instance) 
    .PropertyType; 

Vous pouvez même mettre en cache ces valeurs dans un dictionnaire, donc si trouvé, il suffit de retourner l'entrée dans le dictionnaire, déterminer autrement en utilisant la réflexion et mettre en cache le résultat.

+0

+1 J'ai pensé à la réponse du dictionnaire aussi, mais j'aime beaucoup mieux la réflexion – SwDevMan81

+0

Cette approche hybride coïncide avec toutes les cases IMHO –

+0

Haha, quoi? Tic-tac toutes les cases, je dois avoir raté quelque chose ... ne pouvait même pas trouver celui-ci dans le New Hacker's Dictionary, peut-être un moment pour une révision? – SwDevMan81

0

Oui, vous pouvez utiliser les noms dans l'énumération avec la réflexion sur le type DatabaseRecordInfo pour obtenir les types dont vous avez besoin.

Cela pourrait se faire comme ceci:

public class DataBaseRecordInfo 
{ 
    public long NumID1 { get; set; } 
    public int NumID2 { get; set; } 
    public short NumID3 { get; set; } 

    public static Type GetType(DatabaseField field) 
    { 
     string name = field.ToString(); 
     Type recordType = typeof (DataBaseRecordInfo); 
     var props = recordType.GetProperties(); 
     var matchedProperty = props.Where(p => name == p.Name).FirstOrDefault(); 
     if (matchedProperty == null) 
      return null; // We do not have a matching property. 
     return matchedProperty.PropertyType; 
    } 
}; 

Vous voudrez probablement mettre en cache le résultat dans un dictionnaire, car la réflexion peut être sage performance coûteux.

0

Que diriez-vous quelque chose comme ceci:

public static Type GetType(DatabaseField field) 
{ 
    DataBaseRecordInfo dbri = new DataBaseRecordInfo(); 

    switch (field) 
    { 
    case DatabaseField.NumID1: 
     return dbri.NumID1.GetType(); 
    case DatabaseField.NumID2: 
     return dbri.NumID2.GetType(); 
    case DatabaseField.NumID3: 
    return dbri.NumID3.GetType(); 
    default: 
     return typeof(int); 
    } 
} 

Je sais que vous avez dit sans jamais avoir à créer une instance de DataBaseRecordInfo mais je suppose que vous vouliez dire une instance en dehors de la méthode statique. Personne ne voit jamais cette instance.

+0

Cela crée une instance à chaque fois que la méthode est appelée. Il ne résout pas non plus le problème de maintien en deux endroits. –

+0

Cela ne fonctionnerait pas pour un certain nombre de raisons .. – jsmith

+0

J'ai eu l'impression que le problème de "maintenir les choses en deux endroits" était limité aux types, ce qui s'adresse plutôt bien. Il vous donne même la flexibilité d'utiliser des noms incompatibles. – Sapph

0

Si vous souhaitez lier une valeur enum avec des informations supplémentaires, vous pouvez utiliser votre propre CustomAttribute.

Peut-être que vous avez besoin de quelque chose comme ceci:

public class DatabaseTypeAttribute : Attribute 
{ 
    public DatabaseTypeAttribute(Type type) 
    { 
     Type = type; 
    } 
    public Type Type { get; private set; } 
} 

public enum DatabaseField : int 
{ 
    [DatabaseType(typeof(long))] 
    NumID1 = 1, 
    [DatabaseType(typeof(int))] 
    NumID2 = 2, 
    [DatabaseType(typeof(short))] 
    NumID3 = 3, 
    NumID4 = 4, 
}; 

public static class DatabaseFieldHelper 
{ 
    public static Type GetDatabaseType(this DatabaseField field) 
    { 
     var attributes = (DatabaseTypeAttribute[])typeof(DatabaseField).GetField(Enum.GetName(typeof(DatabaseField), field)) 
      .GetCustomAttributes(typeof(DatabaseTypeAttribute), false); 
     if (attributes.Length == 0) 
      return typeof(int); //returns default type 
     return attributes[0].Type; 

    } 
} 

//prints: NumID1 database type: System.Int64 
Console.WriteLine("NumID1 database type: {0}", DatabaseField.NumID1.GetDatabaseType()); 

//prints: NumID2 database type: System.Int32 
Console.WriteLine("NumID2 database type: {0}", DatabaseField.NumID2.GetDatabaseType()); 

//prints: NumID3 database type: System.Int16 
Console.WriteLine("NumID3 database type: {0}", DatabaseField.NumID3.GetDatabaseType()); 

//prints: NumID4 database type: System.Int32 
Console.WriteLine("NumID4 database type: {0}", DatabaseField.NumID4.GetDatabaseType());