2010-01-22 19 views
6

Tengo una clase que analiza los datos de un archivo de texto delimitado por comas. Tengo una enumeración para los campos que me ayuda a analizar los datos más fácilmente. La clase que analiza todos los registros contiene variables públicas para cada campo y, por supuesto, sus tipos de variables. Necesito obtener el tipo de estas variables en función de la enumeración dada.C# Obtener el tipo de una variable pública basada en un valor de 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 todos se asignan dentro de mi constructor. Sin embargo, quiero obtener estos tipos sin crear una instancia de DataBaseRecordInfo. En este momento mi método estático anterior funcionaría, sin embargo, si quisiera cambiar el tipo de variable, tendría que cambiarlo en 2 lugares. ¿Hay alguna forma de evitar tener que cambiar esto en ambos lugares y mantenerlo como un método estático?

+0

No entiendo la pregunta. ¿Puedes ser más claro? "Sin embargo, quiero obtener estos tipos sin crear una instancia de DataBaseRecordInfo", ¿qué significa eso? – hackerhasid

+0

Significa que tengo scenerios en los que quiero los tipos de esas variables, pero no quiero crear una instancia de esta clase para captar los tipos. – jsmith

Respuesta

4

Si el nombre siempre va a coincidir exactamente, puede hacerlo utilizando la reflexión.

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

Incluso se puede almacenar en caché estos valores en un diccionario, así que si lo encuentra, simplemente devuelva la entrada de diccionario, de lo contrario determinar mediante la reflexión y almacenar en caché el resultado.

+0

+1 Pensé en la respuesta del diccionario también, pero me gusta más la manera de reflexión – SwDevMan81

+0

Este enfoque híbrido cumple todos los requisitos IMHO –

+0

Jaja, ¿qué? Cumple todos los requisitos, debo haberme perdido algo ... ni siquiera pude encontrar este en The New Hacker's Dictionary, tal vez un momento para una revisión? – SwDevMan81

0

Sí, puede usar los nombres en la enumeración junto con la reflexión en el tipo DatabaseRecordInfo para obtener los tipos que necesita.

Esto podría hacerse así:

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

es probable que desee almacenar en caché el resultado en un diccionario, ya que la imagen puede ser costoso en cuanto al rendimiento.

0

¿Qué tal algo como esto:

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

Sé que dijo sin tener que crear una instancia de DataBaseRecordInfo pero estoy suponiendo que significaba una instancia fuera del método estático. Nadie ve esta instancia

+0

Esto crea una instancia cada vez que se llama al método. Tampoco resuelve el problema de mantener cosas en dos lugares. –

+0

Esto no funcionaría por una serie de razones .. – jsmith

+0

Me dio la impresión de que el problema de "mantener cosas en dos lugares" se limitaba a los tipos, lo que se soluciona bastante bien. Incluso le da la flexibilidad de usar nombres que no coinciden. – Sapph

0

Si desea vincular el valor enum con algo de información adicional, puede usar su propia CustomAttribute.

Tal vez usted necesita algo como esto:

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()); 
Cuestiones relacionadas