3

いくつかの属性でタグ付けされたいくつかの小道具を持つクラスがあります。特定の順序で表示したい。これまでのところ、私はそれらを注文することができますが、私が望む順序ではできません。

これは、属性を持つ小道具の簡単な例です

[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();
4

2 に答える 2

1

独自のIComparer<T>実装を作成して、各プロパティの属性を比較できます。

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();
于 2012-09-19T21:46:02.920 に答える
0

リーの助けを借りて、ようやく機能しました。正しいコードは次のとおりです。

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;
            }
        }
    }
于 2012-09-20T16:50:22.537 に答える