How to access the custom attributes of a property using VB.NET

1

I have a solution in VB.NET where I am implementing some custom attributes . One of them is for properties, eg:

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've created an extension function for 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 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 do not know how to access this attribute from the property. The only way I could get it would be if I did a search on an instance of the class, but I do not understand that is the best way to do it in VB.

How to solve?

    
asked by anonymous 25.10.2018 / 22:20

1 answer

1

You can not use the extension method directly as you tried, because the method only applies to PropertyInfo types, and the HelloWorld property is of type String , so you must first get the PropertyInfo fault of this property.

I did a search and saw that you can do this manually, taking the class type and then using the GetProperty() method. You can do this by using the property name, as a String :

Dim propInfoManual As PropertyInfo = GetType(Foo).GetProperty("HelloWorld")

Or you can use the NameOf operator, which prevents 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 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 pick typos at compile time, in that case it gets more complicated and the only way I found it was by using the 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 all 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 lambda extension method without the Me. , I put it just to stay more didactic.

Sources:

  

EDITION

At the time I did not visualize, but now I realized that it is possible to use the simplest extension solution, with parameter String instead of lambda expression, and still have strong typing, NameOf operator:

Dim descExtStr As String = Me.GetPropInfo(NameOf(HelloWorld)).GetDescription()
    
01.11.2018 / 21:58