I have a class, and I am doing some nifty things with reflection.
Now I have a need to add some meta data associated to a particular field when I am assigning a value to the field of a class using reflection (I don't know what the class will be).
I would like to do this without the clients to my implementation knowing (having to do anything special of their own).
Having a designated "meta" field or object within the class would work, but doesn't feel very elegant since it requires the child class to do something to be "compatible". I would like to dynamically attach this meta information to the existing class, but still allow it to be treated like the same class be the rest of the application. I would like to be able to recover this meta information later.
- Class gets passed in
- Values get assigned (mapped) via Reflection with
Meta information attached
- Class returned
*This process should have no side effects in regard normal operations and the object type of the class. To the general application the class should be the same before and after.
- Application does "normal" work with the class (assign values, get values, validate information ,etc.)
- Class gets passed back in later
- Use the values along with meta information to do something
Broken down to the simplest terms, I am basically looking for a way to "Piggy-back" extra information on any arbitrary class instance without special compile-time modification.
I realize this is an odd problem with some odd constraints, but can it be done?
This applies if you need the extra state per type and not instance
Your best bet is to use a custom attribute against the field.
1) So create the attribute:
[AttributeUsage(AttributeTargets.Field)]
public class MyCustomAttribute : Attribute
{
}
2) Decorate the field:
class MyClass
{
[MyCustomAttribute]
private int _myField;
....
}
3) And then in your reflection:
if(fieldInfo.GetCustomAttributes(typeof(MyCustomAttribute), true).Length>0)
{
...
}
If it has got to be in the instance
If data is to be part of the instance then
- either instance needs to allow for its storage
- state needs to be stored on a separate class like a dictionary
Second approach is the one first coming to mind and straightforward to do. On the first note, one can
- Define state as a separate property that can hold info. This is the one you have suggested and you are not happy with.
- Inherit from a base class which provides the extra functionality
- Create a generic type, e.g.
Metadata<T>
which will provide such functionality to all types
I tend to like the third which can encapsulate reflecting the type T
and creating necessary placeholders for storing extra state. Main problem with this is you cannot pass the type to methods as a parameter. Which seems that the second solution is the most practical.
I'd be inclined to create a dictionary with the object instances as the keys and the metadata as the values. You'd probably need to be careful to ensure that equality is determined with ReferenceEquals() rather than Equals(). You might also need a compound key comprising the object and the relevant PropertyInfo.
This approach also wouldn't work if the metadata needs to follow the object into some context where the metadata dictionary is not available.