2011-07-29 37 views
8

Tengo un atributo personalizado que aplico a las propiedades en una clase. Este atributo se usa para exportar las propiedades de la clase a un archivo plano.C# Cómo ordenar propiedades en una clase usando los atributos de propiedad personalizados

Una de las propiedades del atributo es FieldOrder. Necesito asegurarme de que el orden en el que exporto las propiedades de la clase sea correcto. Además, no todas las propiedades de la clase tendrán el atributo personalizado.

Encontré este artículo: How do I sort a generic list based on a custom attribute? Esta solución asume que todas las propiedades tienen el atributo personalizado, que no es mi caso. También esperaba una solución más elegante.

¡Su ayuda es muy apreciada!

public interface IFileExport{} 

public class ExportAttribute: Attribute 
{ 
    public int FieldOrder { get; set; } 

    public int FieldLength { get; set; } 

    public ExportAttribute() { } 

} 

public class ExportClass: IFileExport 
{ 
    [ExportAttribute(FieldOrder = 2, FieldLength = 25)] 
    public string LastName { get; set; } 

    [ExportAttribute(FieldOrder=1, FieldLength=25)] 
    public string FirstName { get; set; } 

    [ExportAttribute(FieldOrder = 3, FieldLength = 3)] 
    public int Age { get; set; } 

    public ExportClass() { } 
} 

public class TestClass 
{ 

    public static List<PropertyInfo> GetPropertiesSortedByFieldOrder(IFileExport fileExport) 
    { 
     //get all properties on the IFileExport object 
     PropertyInfo[] allProperties = fileExport.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public); 

     //now I need to figure out which properties have the ExportAttribute and sort them by the ExportAttribute.FieldOrder 
    } 
} 

ACTUALIZACIÓN: estoy ordenando las propiedades de ExportAttribute.FieldOrder ascendente

+0

Solo un pensamiento, pero tal vez sería más fácil hacer una serialización xml simple, y luego escribir una biblioteca para convertir el simple xml plano en un archivo plano. Sería reutilizable, y podría omitir todo este trabajo de configuración de atributos personalizados y reflexión. – asawyer

Respuesta

22
public static List<PropertyInfo> GetPropertiesSortedByFieldOrder(IFileExport fileExport) 
{ 
    PropertyInfo[] allProperties = GetType() 
     .GetProperties(BindingFlags.Instance | BindingFlags.Public) 
     .Select(x => new 
     { 
      Property = x, 
      Attribute = (ExportAttribute)Attribute.GetCustomAttribute(x, typeof(ExportAttribute), true) 
     }) 
     .OrderBy(x => x.Attribute != null ? x.Attribute.FieldOrder : -1) 
     .Select(x => x.Property) 
     .ToArray(); 
} 

Ya que no explicó cómo quería propiedades sin el atributo ordenada, lo he hecho para que pudieran estar al principio. Pero la esencia de este código es:

  1. Obtener las propiedades
  2. de tirarlos en un tipo anónimo por lo que tiene fácil acceso tanto a la propiedad y el atributo.
  3. Ordene por FieldOrder, usando -1 para propiedades sin el atributo. (No estoy seguro de lo que quería aquí)
  4. transformar la secuencia de nuevo en una secuencia de PropertyInfo
  5. convertirla en una gama PropertyInfo[].
+0

Esto funcionó muy bien. ¡Gracias! – Developer22

0

Usted debe ser capaz de utilizar el método GetCustomAttributes() en cada PropertyInfo para filtrar las propiedades con los atributos correctos, y luego ordenar la restante artículos.

0
 static void Main(string[] args) 
    { 
     //get all properties on the IFileExport object 
     PropertyInfo[] allProperties = fileExport.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public); 
     Array.Sort(allProperties, ArrayAttributeComparison); 


    } 

    private static int ArrayAttributeComparison(PropertyInfo x, PropertyInfo y) 
    { 
     //Do null checks here 
     ExportAttribute xExportAttribute = GetExportAtribute(x); 
     ExportAttribute yExportAttribute = GetExportAtribute(x); 
     //Do null checks here 
     return xExportAttribute.FieldOrder - yExportAttribute.FieldOrder; 
    } 

    private static ExportAttribute GetExportAtribute(PropertyInfo propertyInfo) 
    { 
     object[] attributes = propertyInfo.GetCustomAttributes(true); 
     foreach (var t in attributes) 
     { 
      if (t is ExportAttribute) 
      { 
       return (ExportAttribute)t; 
      } 
     } 
     return null; 
    } 
0

Puede utilizar cualquiera de las siguientes opciones.

Primera opción: pasar función anónima a OrdenarPor

return allProperties.OrderBy(m => m.GetCustomAttribute<ExportAttribute>() == null ? -1 : 
             m.GetCustomAttribute<ExportAttribute>().FieldOrder).ToList(); 

Segunda opción: crear la función para la selección de la tecla y pasarlo a OrdenarPor

return allProperties.OrderBy(KeySelector).ToList(); 

La función de la tecla de selección se define como aquí :

public static int KeySelector(PropertyInfo info) 
    { 
     ExportAttribute attr = info.GetCustomAttribute<ExportAttribute>(); 
     return attr == null ? -1 : attr.FieldOrder; 
    } 

Si la propiedad no tiene ExportAttribute, el sele ctor devolverá -1. Puede elegir cualquier otro valor predeterminado.

El segundo enfoque le permite definir otros tipos de selectores para ordenar y simplemente llame al nuevo selector que ha definido.

Cuestiones relacionadas