【问题标题】:Linq Complex OrderBy by Props attributesLinq Complex OrderBy by Props 属性
【发布时间】:2012-09-19 21:08:16
【问题描述】:

我有一个类,其中一些道具标记有一些属性。我想按特定顺序显示它们。到目前为止,我可以将它们按顺序排列,但不能按我想要的顺序排列。

这里是带有属性的道具的简单示例

[IncludeInEditor]
[IsInPk]
ID
[IncludeInEditor(IsReadOnlyOnModify=true)]
Name
[IncludeInEditor]
Address
[IncludeInEditor]
DOB


The order that I want is:
  1st - Props with IsInPk attribute
  2nd - Props with IncludeInEditor(IsReadOnlyOnModify=true)
  3rd - Props with IncludeInEditor

到目前为止,我没有成功,也没有 100% 完成(仍然缺少 IsReadOnlyOnModify=true 部分)

var properties =
item.GetType().GetProperties()
.Where(p => p.GetCustomAttributes(true)
                            .OfType<IncludeInEditorAttribute>()
                            .Count() > 0)
                .Select (x => new 
                {
                    Property = x,
                    Attribute = (IsInPkAttribute)Attribute.GetCustomAttribute(x, typeof(IsInPkAttribute), true) 
                })
                .OrderBy(x => x.Attribute != null ? 1 : -1)
                .Select(x => x.Property)
                .ToArray();

【问题讨论】:

  • .Count() &gt; 0.Any() 应该更快。
  • 好点奥斯汀!我会重新考虑这一点,我的项目中有很多 Count > 0。 :-(

标签: c# linq sorting attributes sql-order-by


【解决方案1】:

您可以创建自己的IComparer&lt;T&gt; 实现来比较每个属性的属性:

public class AttributeComparer : IComparer<Attribute>
{
    public int Comparer(Attribute x, Attribute y)
    {
        if(x == null) return y == null ? 0 : -1;
        if(y == null) return 1;

        if(x is IsInPkAttribute) return (y is IsInPkAttribute) ? 0 : 1;
        else if(y is IsInPkAttribute) return -1;
        else
        {
            xa = (IncludeInEditorAttribute)x;
            ya = (IncludeInEditorAttribute)y;

            if(xa.IsReadOnlyOnModify == ya.IsReadOnlyOnModify) return 0;
            else return x.IsReadOnlyOnModify ? 1 : -1;
        }
    }
}

那么你的查询变成:

var properties = item.GetType().GetProperties()
    .Where(p => p.GetCustomAttributes(true)
                .OfType<IncludeInEditorAttribute>()
                .Any())
    .Select (x => new 
    {
        Property = x,
        Attribute = Attribute.GetCustomAttribute(x, typeof(IsInPkAttribute), true) ?? Attribute.GetCustomAttribute(x, typeof(IncludeInEditorAttribute, true))
    })
    .OrderBy(x => x.Attribute, new AttributeComparer())
    .Select(x => x.Property)
    .ToArray();

【讨论】:

  • 不太了解您要做什么...在 ELSE 上,您将 x 和 y 都转换为 IncludeInEditorAttribute,而有时 Y 可以是 IsInPkAttribute。
  • @2Fast4YouBR - 好的,我错过了我现在添加的y 的支票。现在只有当xy 都是非空IncludeInEditorAttributes 时才应该到达else 块。
【解决方案2】:

在李的帮助下,终于成功了。正确的代码是:

var properties =
                item.GetType().GetProperties()
                                .Where(p => p.GetCustomAttributes(true)
                                            .OfType<IncludeInEditorAttribute>()
                                            .Any())
                                .Select(x => new
                                {
                                    Property = x,
                                    Attribute = Attribute.GetCustomAttribute(x, typeof(IsInPkAttribute), true)
                                                    ?? Attribute.GetCustomAttribute(x, typeof(IncludeInEditorAttribute), true)
                                })
                                .OrderBy(x => x.Attribute, new IncludeInEditorAttributeComparer())
                                .Select(x => x.Property)
                                .ToArray();

李发来的这段代码,我做了一点改动。

public class IncludeInEditorAttributeComparer : IComparer<Attribute>
    {
        public int Compare(Attribute x, Attribute y)
        {
            //In this case we can assume that
            //won´t have null values

            if (x is IsInPkAttribute && !(y is IsInPkAttribute))
                return -1;
            else if (y is IsInPkAttribute && !(x is IsInPkAttribute))
                return 1;
            else 
            { 
                bool xa = (x is IncludeInEditorAttribute ? (x as IncludeInEditorAttribute).IsReadOnlyOnModify : false);
                bool ya = (y is IncludeInEditorAttribute ? (y as IncludeInEditorAttribute).IsReadOnlyOnModify: false);

                if (xa && !ya)
                    return -1;
                else if (ya && !xa)
                    return 1;
                else
                    return 0;
            }
        }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多