Using the System.Attribute Class

I got into a situation where using the System.Attribute class seemed (at first glance) a good idea.

I have an object to be printed in my application, and I need a shortcut in front of each property (or just a line in front of it). I can put each property hard, like:

Console.WriteLine("Color:"+obj.color); Console.WriteLine("Size:"+obj.size); 

And so on for each property. But instead, I tried to create code where this “shortcut” should not be hard-coded, so I can print each property dynamically.

I got something like this using the System.Attribute class:

 public class MyObject { [MyCustomLabel("Color:")] public string Color; [MyCustomLabel("Size:")] public string Size; //etc... } 

So here is my problem: retrieving this attribute value is not impossible, but it is not very convenient, since I had to use some reflection for it.

I am not very afraid to use reflection, but it seemed that I used attributes for something for which it was not created.

I wonder where are the best places to use attributes, and if this is really the situation for using it.

0
source share
5 answers

Attributes and reflection go hand in hand. Except for some compiler / runtime attributes, there is no way to use them without code reflection.

However, your approach is reasonable, and you can take a look at the attributes in the System.ComponentModel namespace, which have several classes for decorating properties with useful metadata.

+4
source

You are on the right track.

There is also a [DisplayName] attribute specifically designed for this purpose, which has been with .NET since version 2.0.

http://msdn.microsoft.com/en-us/library/system.componentmodel.displaynameattribute.aspx

+1
source

If you just write to the console, that is, debug the output of styles, then what you want is the minimum chance of typo / copy errors.

This is confusing under the hood, but very effective on call sites:

 public static void WriteNameAndValue<T,TValue>( this TextWriter tw, T t, Expression<Func<T, TValue>> getter) { var memberExpression = getter.Body as MemberExpression; if (memberExpression == null) throw new ArgumentException("missing body!"); var member = memberExpression.Member; tw.Write(member.Name); tw.Write(": "); if (member is FieldInfo) { tw.Write(((FieldInfo)member).GetValue(t)); } else if (member is PropertyInfo) { tw.Write(((PropertyInfo)member).GetValue(t, null)); } } public static void WriteNameAndValueLine<T,TValue>( this TextWriter tw, T t, Expression<Func<T, TValue>> getter) { WriteNameAndValue<T,TValue>(tw, t, getter); tw.WriteLine(); } 

then you can write

 t.Foo = "bar"; t.Bar = 32.5; Console.Out.WriteNameAndValueLine(t, x => x.Foo); Console.Out.WriteNameAndValueLine(t, x => x.Bar); // output // Foo: bar // Bar: 32.5 

If you want this to be more customizable at runtime through resources and with considerations for localization, you can do this, but I would consider a different, more standardized approach if that was a likely requirement.

PS if you want a fantasy, you can replace the FieldInfo / PropertyInfo switch with

 tw.Write(getter.Compile()(t)); 

and then you can also check MethodInfo in the expression (or allow arbitrary lambdas and just insert a line number or some other common text. I suggest not letting this route go down, use is already confusing and this can lead to unwanted downloads that should be simple logging method.

+1
source

This is how serialization works, so I would say that your approach is reasonable. Another way you can do this is to create a dictionary of property names and their titles, and then find the name based on the property name.

0
source

I have an object that needs to be printed in my application, and I need a shortcut in front of each property (or just a line in front of it).

Why are you thinking about using attributes in your case? Where do you print these objects in your application.

Maybe just enter ToString in your object

For instance.

 public override string ToString() { StringBuilder sb = new StringBuilder(); sb.Append("PropertyX: "); sb.AppendLine(this.PropertyX); // get string from resource file sb.Append(Resources.FileName); sb.Append(": "); sb.AppendLine(this.FileName); sb.Append("Number: "); sb.AppendLine(this.Number.ToString()); return sb.ToString(); } 
0
source

All Articles