Definition
Attributes – descendants of System.Attribute, some kind of annotations of code, applied for some object.
Standart attributes are
[CLSCompliant] – Common Language Specification
[DLLImport]
[Obsolete] – deprecated
[Serializable]
[NonSerialized]
[WebMethod]
Self made attributes also possible
Attribute consumers
Compiler,
some methods of .NET – for example BinaryFormatter,
CLR
SimpleExample
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// one attribute [Serializable] public class Motorcycle { [NonSerialized] float weightOfCurrentPassengers; bool hasRadioSystem; bool hasHeadSet; bool hasBar; } // many attributes [Serializable,Obsolete("Use another vehicle")] public class Horse { //... } |
Writing like this will add errors to Error list because we used Obsolete
1 2 3 4 |
static void Main(string[] args) { Horse h = new Horse(); } |
ShortNames of Attributes
[SerializableAttribute] and [Serializable] the same in C#
Attributes may recieve params in constructor
1 2 3 4 5 6 7 8 |
public sealed class ObsoleteAttribute : Attribute { public ObsoleteAttribute(); public ObsoleteAttribute(string message); public ObsoleteAttribute(string message, bool error); public bool IsError { get; } public string Message { get; } } |
CustomAttributes
AttributedCarLibrary.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; [assembly: CLSCompliant(true) ] // <<< assembly level attributes namespace AttributedCarLibrary { [AttributeUsage(AttributeTargets.Class| AttributeTargets.Struct,Inherited =false)] public sealed class VehicleDescriptionAttribute:System.Attribute { public string Description { get; set; } public VehicleDescriptionAttribute(string ADescription) { Description = ADescription; } public VehicleDescriptionAttribute() { } } // one attribute [Serializable, VehicleDescription(Description = "My Rocking Harley")] public class Motorcycle { [NonSerialized] float weightOfCurrentPassengers; bool hasRadioSystem; bool hasHeadSet; bool hasBar; } // many attributes [SerializableAttribute] [Obsolete("Use another vehicle")] [VehicleDescription("The old gray mare")] public class Horse { //... } [VehicleDescription("A very long, slow auto")] public class Winnebago { //... } } |
use of custom attributes
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// many attributes [SerializableAttribute] [Obsolete("Use another vehicle")] [VehicleDescription("The old gray mare")] public class Horse { //... } [VehicleDescription("A very long, slow auto")] public class Winnebago { //... } |
AttributeLimitations
we can use class AttributeTargets like this
1 2 3 4 5 6 7 8 9 10 11 |
[AttributeUsage(AttributeTargets.Class| AttributeTargets.Struct,Inherited =false)] public sealed class VehicleDescriptionAttribute:System.Attribute { public string Description { get; set; } public VehicleDescriptionAttribute(string ADescription) { Description = ADescription; } public VehicleDescriptionAttribute() { } } |
Assembly level attributes
- Solution Explorer – > Properties – > AssemblyInfo.cs – fill attributes right in assembly
- Also you can write in code before namespace
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; [assembly: CLSCompliant(true) ] // <<< assembly level attributes namespace AttributedCarLibrary { [AttributeUsage(AttributeTargets.Class| AttributeTargets.Struct,Inherited =false)] public sealed class VehicleDescriptionAttribute:System.Attribute { public string Description { get; set; } public VehicleDescriptionAttribute(string ADescription) { Description = ADescription; } public VehicleDescriptionAttribute() { } } } |
Reflection Attributes with EarlyBinding
1 2 3 4 5 6 7 |
private static void ReflectOnAttributesUsingEarlyBinding() { Type t = typeof(Winnebago); // Knowing type Winnebago, so early binding object[] customAtts = t.GetCustomAttributes(false); foreach (VehicleDescriptionAttribute v in customAtts) Console.WriteLine("->{0}\n",v.Description); } |
full example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using AttributedCarLibrary; namespace ApplyingAttributes { class Program { static void Main(string[] args) { // Horse h = new Horse(); // << Obsolete example ReflectOnAttributesUsingEarlyBinding(); Console.ReadLine(); } private static void ReflectOnAttributesUsingEarlyBinding() { Type t = typeof(Winnebago); object[] customAtts = t.GetCustomAttributes(false); foreach (VehicleDescriptionAttribute v in customAtts) Console.WriteLine("->{0}\n",v.Description); } } } |
Reflection Attributes with lateBinding
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Reflection; namespace AttrReaderLateBinding { class Program { static void Main(string[] args) { ReflectAttsLateBinding(); Console.ReadLine(); } private static void ReflectAttsLateBinding() { try { Assembly asm = Assembly.LoadFrom("AttributedCarLibrary.dll"); Type vehicleDesc = asm.GetType("AttributedCarLibrary.VehicleDescriptionAttribute"); PropertyInfo pDesc = vehicleDesc.GetProperty("Description"); Type[] types = asm.GetTypes(); foreach (Type t in types) { object[] objs = t.GetCustomAttributes(vehicleDesc, false); foreach (object o in objs) { Console.WriteLine("->{0}:{1}\n", t.Name, pDesc.GetValue(o, null)); } } } catch (Exception ex) { Console.WriteLine(ex.Message); } } } } |