How to access the custom attributes of a property using VB.NET
I have a solution in VB.NET where I am implementing some custom attributes . One of them is for properties, example:
Namespace Attributes
<AttributeUsage(AttributeTargets.Property)>
Public Class DescriptionAttribute : Inherits Attribute
Sub New(Name As String)
Me.Name = Name
End Sub
Public Property Name As String
End Class
End Namespace
I need to access the Name
of these attributes coming from the classes, so I created an extension function for the PropertyInfo
, like this:
<Extension()>
Function GetDescription(Prop As PropertyInfo) As String
Dim attr As DescriptionAttribute = Prop.GetCustomAttribute(GetType(DescriptionAttribute))
If (attr IsNot Nothing) Then Return attr.Name
Return Prop.Name
End Function
And I want to be able to use this function anywhere, such as in a Override
Method ToString
:
Public Class Foo
<Description("Hello world with espace")>
Public Property HelloWorld As String
Public Overrides Function ToString() As String
return $"{HelloWorld.GetDescription()} - {HelloWorld}";
End Function
End Class
The problem is that I don't know how to do to access this attribute coming from the property. The only way I could do it would be if I did a search on an instance of the class, but I don't understand that it is the best way to do it in VB.
How to solve?
1 answers
You cannot use the extension method as directly as you tried, because the method applies only to types PropertyInfo
, and the property HelloWorld
is of type String
, so you must first get the PropertyInfo
from that property.
I did some research and saw that you can do this "manually" by taking the type of the class and then using the GetProperty()
method. You can do this by using the property name, such as a String
:
Dim propInfoManual As PropertyInfo = GetType(Foo).GetProperty("HelloWorld")
Or you can use the operator NameOf
, which avoids typos, which will be noticed already at compile time:
Dim propInfoManual As PropertyInfo = GetType(Foo).GetProperty(NameOf(Foo.HelloWorld))
But, if you still want to do an extension method, you can do so if you are going to pass the property name as a String
:
<Extension()>
Public Function GetPropInfo(Of T)(origem As T, prop As String) As PropertyInfo
Return GetType(T).GetProperty(prop)
End Function
If you want that advantage of strong typing, which makes it possible to catch typos at compile time, in this case the thing gets more complicated and the only way I found was using the classes of construction/deconstruction of expressions lambda :
' Necessário para usar as classes de expressões lambda.
Imports System.Linq.Expressions
'[...]
<Extension()>
Public Function GetPropInfo(Of TSource, TProp)(origem As TSource,
seletorProp As Expression(Of Func(Of TProp))
) As PropertyInfo
Select Case seletorProp.Body.NodeType
Case ExpressionType.MemberAccess
Dim memExp As MemberExpression = DirectCast(seletorProp.Body, MemberExpression)
Return DirectCast(memExp.Member, PropertyInfo)
Case Else
Throw New ArgumentException()
End Select
End Function
To test the three methods:
Public Class Foo
<Description("Hello world with space")>
Public Property HelloWorld As String
Public Function DescricaoPropriedade() As String
Dim descManual As String = GetType(Foo).GetProperty(NameOf(Foo.HelloWorld)).GetDescription()
Dim descExtStr As String = Me.GetPropInfo("HelloWorld").GetDescription()
Dim descExtLambda As String = Me.GetPropInfo(Function() Me.HelloWorld).GetDescription()
Return $"Desc manual: {descManual} {vbCrLf}" &
$"Desc estendido (str): {descExtStr} {vbCrLf}" &
$"Desc estendido (lambda): {descExtLambda}"
End Function
End Class
You can also use the extension method with lambda without the Me.
, I put it just to get more didactic.
Sources:
- c# - How to get the PropertyInfo of a specific property? - Stack Overflow
- . net - VB.NET function get property name as string-Stack Overflow
- c # - Retrieving Property name from lambda expression-Stack Overflow
- c # - Extension method to get property name-Stack Overflow
- Extension Methods (Visual Basic) | Microsoft Docs
- Generic Procedures in Visual Basic / Microsoft Docs
Edition
At the time I did not visualize, but now I realized that it is possible to use the simplest solution of extension, with parameter String
instead of expression lambda , and still have strong typing, using here also the operator NameOf
:
Dim descExtStr As String = Me.GetPropInfo(NameOf(HelloWorld)).GetDescription()