Section95.1:Creatingacustomattribute
//1)AllattributesshouldbeinheritedfromSystem.Attribute
//2)Youcancustomizeyourattributeusage(e.g.placerestrictions)byusingSystem.AttributeUsage Attribute
//3)Youcanusethisattributeonlyviareflectioninthewayitissupposedtobeused
//4)MethodMetadataAttributeisjustaname.Youcanuseitwithout”Attribute”postfix-e.g. [MethodMetadata(“Thistextcouldberetrievedviareflection”)].
//5)Youcanoverloadanattributeconstructors [System.AttributeUsage(System.AttributeTargets.Method|System.AttributeTargets.Class)] publicclassMethodMetadataAttribute:System.Attribute
{
//thisiscustomfieldgivenjustforanexample
//youcancreateattributewithoutanyfields
//evenanemptyattributecanbeused-asmarker
publicstringText{get;set;}
//thisconstructorcouldbeusedas[MethodMetadata]
publicMethodMetadataAttribute()
{
}
//Thisconstructorcouldbeusedas[MethodMetadata(“String”)]
publicMethodMetadataAttribute(stringtext)
{
Text=text;
}
}
Section95.2:Readinganattribute
MethodGetCustomAttributesreturnsanarrayofcustomattributesappliedtothemember.Afterretrievingthis arrayyoucansearchforoneormorespecificattributes.
varattribute=typeof(MyClass).GetCustomAttributes().OfType<MyCustomAttribute>().Single();
Oriteratethroughthem
foreach(varattributeintypeof(MyClass).GetCustomAttributes()){ Console.WriteLine(attribute.GetType());
}
GetCustomAttributeextension method from System.Reflection.CustomAttributeExtensionsretrieves a custom attributeofaspecifiedtype,itcanbeappliedtoanyMemberInfo.
varattribute=(MyCustomAttribute)typeof(MyClass).GetCustomAttribute(typeof(MyCustomAttribute));
GetCustomAttributealsohasgenericsignaturetospecifytypeofattributetosearchfor.
varattribute=typeof(MyClass).GetCustomAttribute<MyCustomAttribute>();
Booleanargumentinheritcanbepassedtobothofthosemethods.Ifthisvaluesettotruetheancestorsof element would be also to inspected.
[StackDemo(Text=”Hello,World!”)]
publicclassMyClass
{
[StackDemo(“Hello,World!”)]
staticvoidMyMethod()
{
}
}
Section95.4:DebuggerDisplayAttribute
AddingtheDebuggerDisplayAttributewillchangethewaythedebuggerdisplaystheclasswhenitishoveredover.
Expressions that are wrapped in {}will be evaluated by the debugger. This can be a simple property like in the following sample or more complex logic.
[DebuggerDisplay(“{StringProperty}-{IntProperty}”)]
publicclassAnObject
{
publicintObjectId{get;set;}
publicstringStringProperty{get;set;}
publicintIntProperty{get;set;}
}
Adding,nqbeforetheclosingbracketremovesthequoteswhenoutputtingastring.
[DebuggerDisplay(“{StringProperty,nq}-{IntProperty}”)]
Eventhoughgeneralexpressionsareallowedinthe{}theyarenotrecommended.TheDebuggerDisplayattribute willbewrittenintotheassemblymetadataasastring.Expressionsin{}arenotcheckedforvalidity.Soa DebuggerDisplayattributecontainingmorecomplexlogicthani.e.somesimplearithmeticmightworkfineinC#, butthesameexpressionevaluatedinVB.NETwillprobablynotbesyntacticallyvalidandproduceanerrorwhile debugging.
AwaytomakeDebuggerDisplaymorelanguageagnosticistowritetheexpressioninamethodorpropertyandcall it instead.
[DebuggerDisplay(“{DebuggerDisplay(),nq}”)]
publicclassAnObject
{
publicintObjectId{get;set;}
publicstringStringProperty{get;set;}
publicintIntProperty{get;set;}
privatestringDebuggerDisplay()
{
return$”{StringProperty}-{IntProperty}””;
}
}
OnemightwantDebuggerDisplaytooutputallorjustsomeofthepropertiesandwhendebuggingandinspecting also the type of the object.
The example below also surrounds the helper method with #ifDEBUGas DebuggerDisplayis used in debugging environments.
[DebuggerDisplay(“{DebuggerDisplay(),nq}”)]
publicclassAnObject
{
publicintObjectId{get;set;}
publicstringStringProperty{get;set;}
publicintIntProperty{get;set;}
#ifDEBUG
privatestringDebuggerDisplay()
{
return
$”ObjectId:{this.ObjectId},StringProperty:{this.StringProperty}, Type:{this.GetType()}”;
}
#endif
}
Section95.5:Callerinfoattributes
Caller info attributes can be used to pass down information about the invoker to the invoked method. The declaration looks like this:
usingSystem.Runtime.CompilerServices;
publicvoidLogException(Exceptionex,
[CallerMemberName]stringcallerMemberName=””,
[CallerLineNumber]intcallerLineNumber=0,
[CallerFilePath]stringcallerFilePath=””)
{
//performlogging
}
Andtheinvocationlookslike this:
publicvoidSave(DBContextcontext)
{
try
{
context.SaveChanges();
}
catch(Exceptionex)
{
LogException(ex);
}
}
Notice that only the first parameter is passed explicitly to the LogExceptionmethod whereas the rest of them willbe provided at compile time with the relevant values.
ThecallerMemberNameparameterwillreceivethevalue”Save”-thenameofthecallingmethod.
ThecallerLineNumberparameterwillreceivethenumberofwhicheverlinetheLogExceptionmethodcallis written on.
Andthe’callerFilePath’parameterwillreceivethefullpathofthefileSavemethodisdeclaredin.
System.Obsolete is an attribute that is used to mark a type or a member that has a better version, and thus should not be used.
[Obsolete(“Thisclassisobsolete.UseSomeOtherClassinstead.”)]classSomeClass
{
//
}
Incasetheclassaboveisused,thecompilerwillgivethewarning”Thisclassisobsolete.UseSomeOtherClass instead.”
Section95.7:Readinganattributefrominterface
Thereisnosimplewaytoobtainattributesfromaninterface,sinceclassesdoesnotinheritattributesfroman interface.Wheneverimplementinganinterfaceoroverridingmembersinaderivedclass,youneedtore-declare theattributes.SointheexamplebelowoutputwouldbeTrueinallthreecases.
usingSystem;
usingSystem.Linq;
usingSystem.Reflection;
namespaceInterfaceAttributesDemo{
[AttributeUsage(AttributeTargets.Interface,Inherited=true
)] classMyCustomAttribute:Attribute{
publicstringText{get;set;}
}
[MyCustomAttribute(Text=”Hellofrominterfaceattribute”)]
interfaceIMyClass{
voidMyMethod();
}
classMyClass:IMyClass{
publicvoidMyMethod() { }
}
publicclassProgram{
publicstaticvoidMain(string[]args){
GetInterfaceAttributeDemo();
}
privatestaticvoidGetInterfaceAttributeDemo(){
varattribute1=(MyCustomAttribute)
typeof(MyClass).GetCustomAttribute(typeof(MyCustomAttribute),true);
Console.WriteLine(attribute1==null);//True
varattribute2=
typeof(MyClass).GetCustomAttributes(true).OfType<MyCustomAttribute>().SingleOrDefault();
Console.WriteLine(attribute2==null);//True
varattribute3=typeof(MyClass).GetCustomAttribute<MyCustomAttribute>(true); Console.WriteLine(attribute3==null);//True
}
}
}
Onewaytoretrieveinterfaceattributesistosearchforthemthroughalltheinterfacesimplementedbyaclass.
varattribute=typeof(MyClass).GetInterfaces().SelectMany(x=>x.GetCustomAttributes(
).OfType<MyCustomAttribute>()).SingleOrDefault();
Console.WriteLine(attribute==null);//False
Console.WriteLine(attribute.Text);//Hellofrominterfaceattribute
About us and this blog
We are a digital marketing company with a focus on helping our customers achieve great results across several key areas.
Request a free quote
We offer professional SEO services that help websites increase their organic search score drastically in order to compete for the highest rankings even when it comes to highly competitive keywords.
Subscribe to our newsletter!
More from our blog
See all postsRecent Posts
- Chapter110:Timers 10/05/2024
- Chapter109:Stream 09/05/2024
- Chapter108:CheckedandUnchecked 08/05/2024