Reputation: 13297
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
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