迭代具有特定属性的字段

时间:2013-03-25 17:26:11

标签: c# reflection attributes

我对C#中的反思很陌生。我想创建一个可以与我的字段一起使用的特定属性,因此我可以仔细检查它们并检查它们是否已正确初始化,而不是每次都为每个字段编写这些检查。我认为它看起来像这样:

public abstract class BaseClass {

    public void Awake() {

        foreach(var s in GetAllFieldsWithAttribute("ShouldBeInitialized")) {

            if (!s) {

                Debug.LogWarning("Variable " + s.FieldName + " should be initialized!");
                enabled = false;

            }

        }

    }

}

public class ChildClass : BasicClass {

    [ShouldBeInitialized]
    public SomeClass someObject;

    [ShouldBeInitialized]
    public int? someInteger;

}

(您可能会注意到我打算使用它Unity3d,但在这个问题上没有任何特定的Unity - 或者至少,对我来说似乎是这样)。这可能吗?

1 个答案:

答案 0 :(得分:2)

你可以用一个简单的表达式得到它:

private IEnumerable<FieldInfo> GetAllFieldsWithAttribute(Type attributeType)
{
    return this.GetType().GetFields().Where(
        f => f.GetCustomAttributes(attributeType, false).Any());
}

然后将您的电话改为:

foreach(var s in GetAllFieldsWithAttribute(typeof(ShouldBeInitializedAttribute)))

您可以在Type上将其作为一种扩展方法,在整个应用中使其更有用:

public static IEnumerable<FieldInfo> GetAllFieldsWithAttribute(this Type objectType, Type attributeType)
{
    return objectType.GetFields().Where(
        f => f.GetCustomAttributes(attributeType, false).Any());
}

您可以将其称为:

this.GetType().GetAllFieldsWithAttribute(typeof(ShouldBeInitializedAttribute))

修改:要获取私人字段,请将GetFields()更改为:

GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)

获取类型(在循环内):

object o = s.GetValue(this);