Know who is implementing it per its instance?
For example, I create the Attribute
MySpecialAttribute
Extends Attribute, it can apply to anything.
When I use this attribute on on a property, is there any way for the Attribute to know who its 'parent' is?
I can't see anything related in memberinfo, fieldinfo, propertyinfo, type, or anything shared in attribute that knows this.
-
-
stevo_ wrote:Know who is implementing it per its instance?
For example, I create the Attribute
MySpecialAttribute
Extends Attribute, it can apply to anything.
When I use this attribute on on a property, is there any way for the Attribute to know who its 'parent' is?
I can't see anything related in memberinfo, fieldinfo, propertyinfo, type, or anything shared in attribute that knows this.
So you want your Attribute to know what member or type it is applied to or just find its base class?
-
What it's applied to.
Also, I know this generally might seem pointless, but I was looking for some context in case I wanted to add some additional exception grabbing.
For example, I may have an attribute that provides a Type, but I actually want the type to implement a specific interface or base class etc. -
No. It does not know. An attribute is just plain and simple metadata, packed into a class. I was wondering the same a few years ago - while doing some coding at my ORM.
What did I do to do the checks: I took the problem from the other side. I have a class that all objects with attributes need to pass through. That class also uses the attributes to do some special stuff (like setting the values from the database to the properties etc). That class checks the attributes and fires an exception if the attribute is set, but something is not matching. In your case it would fire an exception if an interface is not implement, but the attribute is specified...
I'm sure you have a class that inspects the type and checks for attributes on it... That's the place where the validation code needs to be put in. -
Btw. if you query an attribute (by using Attribute.GetCustomAttribute or type.GetCustomAttributes()) do you think you get always the same instance? No! On each query an instance of the class is created from metadata. Look at this code:
public Program()
{
FooAttribute f1 = (FooAttribute)Attribute.GetCustomAttribute(this.GetType(), typeof(FooAttribute));
FooAttribute f2 = (FooAttribute)Attribute.GetCustomAttribute(this.GetType(), typeof(FooAttribute));
if (f1 == f2)
Console.WriteLine("Equal");
else
Console.WriteLine("No they don't equal");
Console.Read();
}
The output is "No they don't equal". If you would have defined code in the constructor of the attribute class (FooAttribute here) it would get run on each request!
What I usually do (to gain speed) is to cache the returned attributes in a cache that holds the connection between the attributes and the type. I have done that because my classes could have 50+ attributes specified and I want them to query as I like it - also based on some attributes data etc.
But I take the attributes as what they are: enhanced metadata that allow me to specify methods and properties
Just as a side note
Edit: Also if you would set a property (programmatically) on an instance of an attribute and query it again that changes are lost, because the attribute instance is recreated and the old one (where you changed the property) is lost! If you need to have those changes permanently, you need to cache the attribute instances! -
Interesting, yes I have a class that does inspection. The other part that I was looking into was default values, where an attribute would be able to determine the default value of one of its properties, based upon what it was applied to.
I realised this may actually destroy the idea of an attribute, since the values you getting were not the ones you literally set.
As such, I was looking into the best way to provide default values, the most easy and perhaps the most correct way to reflect what an attribute was, is for specific 'configuration' classes to be created that take a MemberInfo (and perhaps the attribute) and really just reflect the properties of the attribute its looking for, but will determine the default values itself unless the attribute specifically supplies it.
This way the 'mapper' class doesn't get bloated down with lots of these checks.
Now I just need to think of the best way to make these configuration classes extensible.
(perhaps attributes on the attribute classes
)
My only concern was that my mapping class was starting to do a lot of work, not only was it doing the mapping, which tends to be somewhat long, it was also having to determine the defaults and validations for the Member-Attribute pair.
I was really just looking for the best way to abstract this away from the mapping class, to keep it cleaner and more reusable. -
What I did is to create a mapping class. That class holds the whole mapping for a type. I store that in a dictionary with the type as key. I have also a MappingCreator class that creates the mapping for a specific type. It's only class design, to make it somehow modular and extensible.
-
steve, I think you are heading into the wrong direction.
As has been said Attributes are *META*Data. If you want to have a default value that is used in the program itself for something directly related to other settings its just other data and not metadata.
A simple way to set a default would be to simply add a readonly virtual property providing the value. -
Thanks for the input, but if you read through the thread, you'll notice I made the same observation about default values being misleading and somewhat corruptive, if applied to the attribute itself.
Thread Closed
This thread is kinda stale and has been closed but if you'd like to continue the conversation, please create a new thread in our Forums,
or Contact Us and let us know.