C# - 如何按声明顺序对Type.GetFields()返回的字段进行排序?

时间:2012-04-02 13:22:44

标签: c# reflection

Type.GetFields()不按特定顺序返回字段,但我想按声明顺序对它们进行排序。我怎样才能做到这一点?我没有在FieldInfo中看到'index'属性或任何具有类似功能的东西。

动机:我想实现类似于this answer中的位域解决方案,但正如第二条评论所述,订单无法保证。

编辑:澄清 - 我不想创建此代码来依赖此排序。我想创建这个代码来解析已经有一定排序的现有二进制数据。


编辑2(回答后):我选择了一个完全回答问题的答案,并且在我的测试中正常运行,但是作为旁注,位域解决方案存在问题:< / p>

从位字段读取值时,您会得到一个无符号整数(某个大小),但是根据您在运行时获得的实际字段类型(byte,bool,int),您无法正确转换它。 FieldInfo。您可以使用运行时显式条件(if type.Equals(typeof(bool))等)来完成它,但这有点难看。

我最终使用了C ++ / CLI,这使得这更加简单。

5 个答案:

答案 0 :(得分:5)

您可以编写声明订单的自定义属性。然后,对于每个字段,查找该属性。使用值进行排序。

这不会是自动的,但这将是一种非常确定的方式。

使用示例:

[Index(0)]
private int myField;

[Index(1)]
private int myOtherField;

答案 1 :(得分:2)

您可以向属性

添加位置信息
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class BitfieldAttribute : Attribute 
{ 
    public BitfieldAttribute(int position, int length) 
    { 
        this.Position = position; 
        this.Length = length; 
    } 

    public int Position { get; private set; }

    public int Length { get; private set; }
}

然后你就可以通过像这样的字段进行迭代了

foreach (FieldInfo fld in type.GetFields().OrderBy(f => f.Position)) {
    ...
}

此属性将像这样使用

struct PESHeader 
{ 
    [Bitfield(0, 2)] 
    public uint reserved; 

    [Bitfield(1, 2)] 
    public uint scrambling_control; 

    [Bitfield(2, 1)] 
    public uint priority; 

    [Bitfield(3, 1)] 
    public uint data_alignment_indicator; 

    [Bitfield(4, 1)] 
    public uint copyright; 

    [Bitfield(5, 1)] 
    public uint original_or_copy; 
}

与字母顺序相比,优势在于您可以控制稍后添加的新字段的位置,从而避免现有字段的位置发生变化。

答案 2 :(得分:1)

您可以像这样扩展BitFieldLength属性:

sealed class BitfieldLengthAttribute : Attribute
{
    uint index;
    uint length;

    public BitfieldLengthAttribute(uint index, uint length)
    {
        this.index = index;
        this.length = length;
    }

    public uint Index { get { return index; } }
    public uint Length { get { return length; } }
}

然后手动为所有字段添加索引,检索列表中的类型并对属性索引上的列表进行排序。

答案 3 :(得分:0)

您可以使用Linq来对象并编写如下代码:

var fields = type.GetFields().OrderBy(f => f.Name).ToArray();

答案 4 :(得分:0)

在此link它表示按MetadataToken排序以获得减速顺序。 这意味着:

            IEnumerable<FieldInfo> fields = t.GetFields().OrderBy(f=>f.MetadataToken);

我真的不明白它的工作原理,但现在它对我来说很好。

相关问题