2011-06-18 13 views
5

quiero conseguir todos los campos que tienen valores nulos, pero i no es siquiera conseguir cualquier campo:consigo campos con la reflexión

[Serializable()] 
public class BaseClass 
{ 
    [OnDeserialized()] 
    internal void OnDeserializedMethod(StreamingContext context) 
    { 
     FixNullString(this); 
    } 

    public void FixNullString(object type) 
    { 
     try 
     { 
      var properties = type.GetType().GetFields(); 


      foreach (var property in from property in properties 
            let oldValue = property.GetValue(type) 
            where oldValue == null 
            select property) 
      { 
       property.SetValue(type, GetDefaultValue(property)); 
      } 
     } 
     catch (Exception) 
     { 

     } 
    } 

    public object GetDefaultValue(System.Reflection.FieldInfo value) 
    { 
     try 
     { 
      if (value.FieldType == typeof(string)) 
       return ""; 

      if (value.FieldType == typeof(bool)) 
       return false; 

      if (value.FieldType == typeof(int)) 
       return 0; 

      if (value.FieldType == typeof(decimal)) 
       return 0; 

      if (value.FieldType == typeof(DateTime)) 
       return new DateTime(); 
     } 
     catch (Exception) 
     { 

     } 

     return null; 
    } 
} 

y luego tengo una clase:

[Serializable()] 
public class Settings : BaseClass 
{ 
    public bool Value1 { get; set; } 
    public bool Value2 { get; set; } 
} 

Pero cuando viene a

var properties = type.GetType().GetFields(); 

Luego obtengo 0 campos, debería encontrar 2 campos.

¿Es incorrecto usar type.getType(). GetFields()? o estoy enviando la clase incorrecta a la clase base?

Respuesta

13

Type.GetFields métodos devuelve todos campos públicos Los campos que el compilador autogenera para usted son privados, por lo que debe especificar BindingFlags correctos.

type.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic) 
1

Value1 y Value2 en su clase Settings son propiedades lugar de los terrenos, por lo que tendrá que utilizar GetProperties() para acceder a ellos.

(Utilizando la sintaxis { get; set; } le dice al compilador que desea una propiedad, sino que debe generar el get y set para usted, junto con un campo privado oculto que contiene los datos.)

0

Los campos generados por el compilador correspondiente a propiedades de su clase tienen el atributo CompilerGenerated. Además, el compilador generará los métodos get y set para manejar estos campos, según la declaración de su propiedad.

De documentación CompilerGeneratedAttribute MSDN:

distingue a un elemento generado por el compilador de un elemento generado por el usuario. Esta clase no puede heredarse.

El nombre de estos campos tienen el formato <PropertyName>k_BackingField, los métodos y setget nombres tienen el formato set_PropertyName y get_PropertyName donde PropertyName es el nombre de la propiedad.

Por ejemplo, la clase de Settings se compila la siguiente manera:

[Serializable] 
public class Settings : BaseClass 
{ 
    public Settings(){} 

    // Properties 
    [CompilerGenerated] 
    private bool <Value1>k__BackingField; 

    [CompilerGenerated] 
    private bool <Value2>k__BackingField; 

    [CompilerGenerated] 
    public void set_Value1(bool value) 
    { 
     this.<Value1>k__BackingField = value; 
    } 

    [CompilerGenerated] 
    public bool get_Value1() 
    { 
     return this.<Value1>k__BackingField; 
    } 

    [CompilerGenerated] 
    public void set_Value2(bool value) 
    { 
     this.<Value2>k__BackingField = value; 
    } 

    [CompilerGenerated] 
    public bool get_Value2() 
    { 
     return this.<Value2>k__BackingField; 
    } 
} 

Si desea excluir estos campos de respaldo puede utilizar este método:

public IEnumerable<FieldInfo> GetFields(Type type) 
{ 
    return type 
     .GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) 
     .Where(f => f.GetCustomAttribute<CompilerGeneratedAttribute>() == null); 
} 
Cuestiones relacionadas