C# Linq复杂OrderBy Props属性

C# Linq复杂OrderBy Props属性,c#,linq,sorting,attributes,sql-order-by,C#,Linq,Sorting,Attributes,Sql Order By,我有一个带有一些属性标记的道具的类。我想按特定顺序显示它们。到目前为止,我可以把它们按顺序排列,但不是按我想要的顺序排列 下面是一个带有属性的道具的简单示例 [IncludeInEditor] [IsInPk] ID [IncludeInEditor(IsReadOnlyOnModify=true)] Name [IncludeInEditor] Address [IncludeInEditor] DOB The order that I want is: 1st - Props wit

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

下面是一个带有属性的道具的简单示例

[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属性=
item.GetType().GetProperties()
.Where(p=>p.GetCustomAttributes(true)
第()类
.Count()>0)
.选择(x=>new
{
属性=x,
Attribute=(IsInPkAttribute)Attribute.GetCustomAttribute(x,typeof(IsInPkAttribute),true)
})
.OrderBy(x=>x.Attribute!=null?1:-1)
.Select(x=>x.Property)
.ToArray();

您可以创建自己的
IComparer
实现来比较每个属性上的属性:

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;
        }
    }
}
公共类属性比较者:IComparer
{
公共整数比较器(属性x、属性y)
{
如果(x==null)返回y==null?0:-1;
如果(y==null)返回1;
如果(x为IsInputAttribute)返回(y为IsInputAttribute)?0:1;
否则,如果(y是IsInputAttribute)返回-1;
其他的
{
xa=(IncludeInEditorAttribute)x;
ya=(包含编辑属性)y;
如果(xa.IsReadOnlyOnModify==ya.IsReadOnlyOnModify)返回0;
否则返回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();
var properties=item.GetType().GetProperties()
.Where(p=>p.GetCustomAttributes(true)
第()类
.Any())
.选择(x=>new
{
属性=x,
Attribute=Attribute.GetCustomAttribute(x,typeof(IsInputAttribute),true)??Attribute.GetCustomAttribute(x,typeof(IncludeInEditorAttribute,true))
})
.OrderBy(x=>x.Attribute,新的AttributeComparer())
.Select(x=>x.Property)
.ToArray();

在李的帮助下,它终于开始工作了。正确的代码是:

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();
var属性=
item.GetType().GetProperties()
.Where(p=>p.GetCustomAttributes(true)
第()类
.Any())
.选择(x=>new
{
属性=x,
Attribute=Attribute.GetCustomAttribute(x,typeof(IsInputAttribute),true)
?属性.GetCustomAttribute(x,类型(IncludeInEditorAttribute),真)
})
.OrderBy(x=>x.Attribute,新的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;
            }
        }
    }
公共类includeEditorAttributeComparer:IComparer
{
公共整数比较(属性x、属性y)
{
//在这种情况下,我们可以假设
//不会有空值
如果(x是IsInPkAttribute&&!(y是IsInPkAttribute))
返回-1;
否则,如果(y是IsInPkAttribute&!(x是IsInPkAttribute))
返回1;
其他的
{ 
bool xa=(x为IncludeInEditorAttribute?(x为IncludeInEditorAttribute)。IsReadOnlyOnModify:false);
bool ya=(y是IncludeInEditorAttribute?(y是IncludeInEditorAttribute)。IsReadOnlyOnModify:false);
if(xa&&!ya)
返回-1;
else if(ya&&!xa)
返回1;
其他的
返回0;
}
}
}

.Count()>0
.Any()
应该更快。奥斯汀说得对!我会重新考虑这一点,我的项目中有很多计数>0-(我不太明白您想做什么……在ELSE上,您正在将x和y都转换为IncludeEditorAttribute,而有时y可以是IsInputAttribute。@2Fast4YouBR-好的,我没有检查我现在添加的
y
。现在只有当
x
y
都是非空
时,才能到达ELSE块cludeInEditorAttribute
s。
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;
            }
        }
    }