Max Yankov
Max Yankov

Reputation: 13297

Iterating through fields with specific attribute

I'm pretty new to reflection in C#. I want to create a specific attribute that I can use with my fields, so I can go through them all and check that they are initialized properly, instead of writing these checks every time for every field. I think it would look something like this:

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;

}

(You may notice that I intend to use it Unity3d, but there's nothing specific to Unity in this question — or at least, it seems so to me). Is this possible?

Upvotes: 1

Views: 498

Answers (1)

Steve Czetty
Steve Czetty

Reputation: 6228

You can get this with a simple expression:

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

Then change your call to:

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

You can make this more useful throughout your app by making it an extension method on Type:

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

You would call this as:

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

Edit: To get private fields, change GetFields() to:

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

And to get the type (inside your loop):

object o = s.GetValue(this);

Upvotes: 2

Related Questions