遍历具有特定属性的字段

本文关键字:属性 字段 遍历 | 更新日期: 2023-09-27 18:05:52

我对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的-或者至少,对我来说似乎是这样)。这可能吗?

遍历具有特定属性的字段

您可以通过一个简单的表达式获得:

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))

Edit:要获取私有字段,将GetFields()更改为:

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

获取类型(在循环内):

object o = s.GetValue(this);