【问题标题】:How to sort properties on a class using custom property attributes如何使用自定义属性属性对类的属性进行排序
【发布时间】:2011-07-29 18:01:44
【问题描述】:

我有一个自定义属性应用于类的属性。此属性用于将类的属性导出到平面文件。

属性的属性之一是FieldOrder。我需要确保导出类属性的顺序正确。此外,并非类上的所有属性都具有自定义属性。

我找到了这篇文章:How do I sort a generic list based on a custom attribute? 这个解决方案假定所有属性都具有自定义属性,这不是我的情况。我也希望有更优雅的解决方案。

非常感谢您的帮助!

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

更新:我按 ExportAttribute.FieldOrder Ascending 排序属性

【问题讨论】:

  • 只是一个想法,但也许做一个简单的xml序列化会更容易,然后编写一个库将简单的平面xml转换为平面文件。它可以重复使用,您可以跳过所有这些自定义属性设置工作和反射。

标签: c# sorting attributes properties


【解决方案1】:
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();
}

由于您没有解释您想要没有订购属性的属性,所以我已经将它们放在开头。但是这段代码的要点是:

  1. 获取属性
  2. 将它们放入匿名类型中,以便您可以轻松访问属性和属性。
  3. FieldOrder 排序,对没有属性的属性使用-1。 (不知道你想要什么)
  4. 将序列转换回PropertyInfo的序列
  5. 将其转换为PropertyInfo[] 数组。

【讨论】:

    【解决方案2】:

    您可以使用以下任一选项。

    第一个选项:将匿名函数传递给 OrderBy

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

    第二个选项:创建选择键的函数并将其传递给 OrderBy

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

    按键选择器函数定义如下:

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

    如果属性没有 ExportAttribute,则选择器将返回 -1。您可以选择任何其他默认值。

    第二种方法允许您定义其他类型的选择器进行排序,只需调用您定义的新选择器。

    【讨论】:

      【解决方案3】:

      您应该能够对每个 PropertyInfo 使用 GetCustomAttributes() 方法来过滤具有正确属性的属性,然后对剩余的项目进行排序。

      【讨论】:

        【解决方案4】:
                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;
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-01-18
          • 1970-01-01
          • 2020-07-20
          • 1970-01-01
          • 1970-01-01
          • 2011-02-16
          相关资源
          最近更新 更多