So a little confession, I've never written an attribute class. I understand they serve the purpose of decorating classes with flags or extra functionality possibly.
Can someone give me a quick example of not just creating and applying an attribute to a class, but rather utilizing the attribute from another block of code. The only code samples I've ever seen to utilize any form of attributes was doing so with reflection, though I've always hoped there's a way of using them without reflection.
Attributes are always used with reflection. They are baked into the metadata of the types during compile time and the only way to read them is through reflection. Attributes are used when you want write a type and you want to associate some metadata with it which could be used by consumers of this type.
The simplest and most elegant way to use an attribute from another block of code is to use a property instead of an attribute.
See http://blogs.msdn.com/b/ericlippert/archive/2009/02/02/properties-vs-attributes.aspx for a discussion of the differences between properties and attributes.
First create your attribute
public class ImportableAttribute : Attribute
{
}
Then a class with a item that uses the Attribute
[ImportableAttribute]
public class ImportClass
{
[ImportableAttribute]
public string Item {get; set;}
}
Then check if that property uses that attribute. Can be done with classes to.. Of course :)
PropertyInfo property = typeof(ImportClass).GetProperty("Item");
if (property.IsDefined(typeof(ImportableAttribute),true))
{
// do something
}
With a class:
typeof(ImportClass).IsDefined(typeof(ImportableAttribute), true);
Related
I'm creating a custom attribute in C# and I want to do different things based on whether the attribute is applied to a method versus a property. At first I was going to do new StackTrace().GetFrame(1).GetMethod() in my custom attribute constructor to see what method called the attribute constructor, but now I'm unsure what that will give me. What if the attribute was applied to a property? Would GetMethod() return a MethodBase instance for that property? Is there a different way of getting the member to which an attribute was applied in C#?
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property,
AllowMultiple = true)]
public class MyCustomAttribute : Attribute
Update: okay, I might have been asking the wrong question. From within a custom attribute class, how do I get the member (or the class containing the member) to which my custom attribute was applied? Aaronaught suggested against walking up the stack to find the class member to which my attribute was applied, but how else would I get this information from within the constructor of my attribute?
Attributes provide metadata and don't know anything about the thing (class, member, etc.) they are decorating. On the other hand, the thing being decorated can ask for the attributes it is decorated with.
If you must know the type of the thing being decorated you will need to explicitly pass it to your attribute in its constructor.
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property,
AllowMultiple = true)]
public class MyCustomAttribute : Attribute
{
Type type;
public MyCustomAttribute(Type type)
{
this.type = type;
}
}
Since there seems to be a lot of confusion with respect to how the stack frames and methods work, here is a simple demonstration:
static void Main(string[] args)
{
MyClass c = new MyClass();
c.Name = "MyTest";
Console.ReadLine();
}
class MyClass
{
private string name;
void TestMethod()
{
StackTrace st = new StackTrace();
StackFrame currentFrame = st.GetFrame(1);
MethodBase method = currentFrame.GetMethod();
Console.WriteLine(method.Name);
}
public string Name
{
get { return name; }
set
{
TestMethod();
name = value;
}
}
}
The output of this program will be:
set_Name
Properties in C# are a form of syntactic sugar. They compile down to getter and setter methods in the IL, and it's possible that some .NET languages might not even recognize them as properties - property resolution is done entirely by convention, there aren't really any rules in the IL spec.
Now, let's say for the moment that you had a really good reason for a program to want to examine its own stack (and there are precious few practical reasons to do so). Why in the world would you want it to behave differently for properties and methods?
The whole rationale behind attributes is that they are a kind of metadata. If you want a different behaviour, code it into the attribute. If an attribute can mean two different things depending on whether it's applied to a method or property - then you should have two attributes. Set the target on the first to AttributeTargets.Method and the second to AttributeTargets.Property. Simple.
But once again, walking your own stack to pick up some attributes from the calling method is dangerous at best. In a way, you are freezing your program's design, making it far more difficult for anybody to extend or refactor. This is not the way attributes are normally used. A more appropriate example, would be something like a validation attribute:
public class Customer
{
[Required]
public string Name { get; set; }
}
Then your validator code, which knows nothing about the actual entity being passed in, can do this:
public void Validate(object o)
{
Type t = o.GetType();
foreach (var prop in
t.GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
if (Attribute.IsDefined(prop, typeof(RequiredAttribute)))
{
object value = prop.GetValue(o, null);
if (value == null)
throw new RequiredFieldException(prop.Name);
}
}
}
In other words, you're examining the attributes of an instance that was given to you but which you don't necessarily know anything about the type of. XML attributes, Data Contract attributes, even Attribute attributes - almost all attributes in the .NET Framework are used this way, to implement some functionality that is dynamic with respect to the type of an instance but not with respect to the state of the program or what happens to be on the stack. It is very unlikely that you are actually in control of this at the point where you create the stack trace.
So I'm going to recommend again that you don't use the stack-walking approach unless you have an extremely good reason to do so which you haven't told us about yet. Otherwise you are likely to find yourself in a world of hurt.
If you absolutely must (don't say we didn't warn you), then use two attributes, one that can apply to methods and one that can apply to properties. I think you'll find that to be much easier to work with than a single super-attribute.
GetMethod will always return you the function name. If it is a property, you will get either get_PropertyName or set_PropertyName.
A property is basically a type of method, so when you implement a property, the compiler creates two separate functions in the resulting MSIL, a get_ and a a set_ methods. This is why in the stack trace you receive these names.
custom attributes are activated by some code calling the GetCustomAttributes method on the ICustomAttributeProvider (reflection object) that represents the location where the attribute is applied. So in the case of a property, some code would obtain the PropertyInfo for the property and then call GetCustomAttributes on that.
If you want to build out some validation framework you would need to write the code that inspects types & members for custom attributes. You could for example have an interface that attributes implement to participate in your validation framework. Could be as simple as the following:
public interface ICustomValidationAttribute
{
void Attach(ICustomAttributeProvider foundOn);
}
Your code could look for this inteface on (for example) a Type:
var validators = type.GetCustomAttributes(typeof(ICustomValidationAttribute), true);
foreach (ICustomValidationAttribute validator in validators)
{
validator.Attach(type);
}
(presumably you would walk the whole reflection graph and do this for each ICustomAttributeProvider). For an example of a similar approach in action in the .net FX you can look at WCF's 'behaviors' (IServiceBehavior, IOperationBehavior, etc).
Update: the .net FX does have a sort-of general purpose, but basically undocumented interception framework in the form of ContextBoundObject and ContextAttribute. You can search the web for some examples of using it for AOP.
I have a class which is has tons of properties. Most of them are of custom types. I want to get all those properties, type of whose interface is same.
Public class abc:IamLegend
{
few properties
}
public class def:IamLegend
{
few properties
}
public class on_which_iamworking
{
public abc propabc{ get; set; }
public def propdef{ get; set; }
public someothertype propother{ get; set; }
}
I want something which returns propabc and propdef.
I know how to do it using reflection, but I am looking for another way.
I am working on c# 4.0
Thanks
I am afraid that this is not possible at runtime without using reflection. That's what reflection is designed for.
The main problem of reflection is that it is slow. If you don't want to use reflection only because of it's slowness, you could make caching of your property list in some static property or class. I used this tecknique widely in similar problems and there wasn't any problems with perfomance.
If you have holy war against reflection, you could create a special util that parses C# file (or builds your prokects, loads output assembly and use reflection, but only before build, not in run-time), finds needed properties and writes it into autogenerated file (maybe also C# code file) as static-class array-property initializer. And call that util on pre-build event of your project. Then you'll get all needed properties completely without reflections =) (but I wouldn't do that)
Well, there's two ways:
1/
return new List<string> { "propabc", "propdev" };
2/ Reflection :P
If you need to retrieve the list of properties many times and are afraid of the performance impact, compute the list only once and store it in a static property (as the list of properties of a class won't change during runtime).
There is an alternative approach for components. It is TypeDescriptor for classes that implement IComponent. I believe that is used by WPF.
Example:
[OnlyShowIfValueIsNonZero]
public int Foo { get; set; }
In the code for OnlyShowIfValueIsNonZero, I need to be able to query the value of Foo. Is this possible? If yes, how?
An attribute is not aware of the member it is assigned to, and for an attribute an instance will only be created if you access it via reflection. You cannot let an attribute interact with code directly - there are some frameworks like PostSharp though that inject code at compile time using attributes.
You can however from reflection supply the member it is assigned to, and since you already need the member to access its attributes, you could create a method in that attribute that accepts the member as parameter.
I think you're starting to get into the world of aspect orientated programming here. Many AOP frameworks provide extensibility points to define your own custom aspects - which is what I think would suit you.
PostSharp is a very popular AOP framework for .NET
maybe , it is like this.
and for example , T is your class...
foreach (PropertyInfo propertyInfo in (typeof(T)).GetProperties()){
foreach (object attribute in propertyInfo.GetCustomAttributes(true))
{
if ( attribute is OnlyShowIfValueIsNonZero )
{
......
}
}
}
I am using PostSharp to add some compile time logic to my attributes - in once case [IndexedCategory ("CatName", CatIndex)]. The trouble comes comes in because IndexedCategory derives from CompoundAspect - which has a reasonable number of named params.
Is there any way which I can prevent these from being accessed / shown by intellisence?
Cheers
I tried a few things... one sure fire way of getting it not to compile would be to re-declare the properties as obsolete or take away the setter - not nice, though.
I tried a few other settings (non-browsable, marked immutable*), but it didn't help much:
[ImmutableObject(true)] // I'm sure this used to toggle intellisense for attribs
public class FooAttribute : BarAttribute
{
[EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]
[ReadOnly(true)]
public new string Name { get { return base.Name; } }
}
Anyway, in the above Name can't be set for an attribute, even though it can on the base. Hacky and ugly.
I think you should rethink your design. I'm not sure inheritance is the way to go, maybe composition would better suite your needs. Without knowing more about what you're trying to accomplish, it's really hard to give concrete examples, but if you don't need the properties of the base class, why are you inheriting from it?
I have a custom attribute which can be assigned to a class, [FooAttribute]. What I would like to do, from within the attribute, is determine which type has actually used me. e.g. If I have:
[FooAttribute]
public class Bar
{
}
In the code for FooAttribute, how can I determine it was Bar class that added me? I'm not specifically looking for the Bar type, I just want to set a friendly name using reflection. e.g.
[FooAttribute(Name="MyFriendlyNameForThisClass")]
public class Bar
{
}
public class FooAttribute()
{
public FooAttribute()
{
// How do I get the target types name? (as a default)
}
}
First off, you might consider the existing [DisplayName] for keeping friendly names. As has already been covered, you simply can't get this information inside the attribute. You can look up the attribute from Bar, but in general, the only way to do it from the attribute would be to pass the type into the attribute - i.e.
[Foo("Some name", typeof(Bar)]
What exactly is it you want to do? There may be other options...
Note that for i18n, resx, etc; you can subclass DisplayNameAttribute and provide lookup from keys by overriding the DisplayName getter.
To elaborat. A attribute, built in or custom, is just meta data for a class, or class member, and the attribute itself nas no notation that it's being associated with something.
The type knows of it's own metadata
The meta data (in this case, the attribute) does not know to whom it belongs
From your sentence "I just want to set a friendly name using reflection" I think you want to set the "MyFriendlyNameForThisClass" name to the attribute at runtime. if so, I don't think that's possible. Please see this thread.
It is clumsy but you could iterate over all classes in the assembly, testing each for the custom attribute that "is" this instance.