4

If let's say I have the following classes:

Public Class Vehicle
        Sub New()
            Car = New Car()
            VehicleName = String.Empty
        End Sub

        Public Property Car As Car

        <Mask()>
        Public Property VehicleName As String
    End Class

    Public Class MaskAttribute
        Inherits Attribute

        Public Property Masking As String
    End Class

    <Serializable()>
     Public Class Car
        Sub New()
            CarName = String.Empty
        End Sub

        <Mask()>
        Public Property CarName As String
    End Class

In the above sample codes, there is a custom attribute name Mask.

Given, there is an object Dim v As new Vehicle()

How to get all the properties of that object which have Mask custom attributes?

So in this case, the expected looping through it are Properties: CarName, and VehicleName as they both have mask attribute

I understand if I use reflection the performance would be slower rather than using lambda expression. Please correct me if I am wrong.

Any idea to achieve that objective using lambda expression?

Thanks!

Hatjhie
  • 1,366
  • 2
  • 13
  • 27
  • 4
    I have no idea how you'd like to do this using lambda expression, without using reflection. These two are totally different things, and lambda expression (or expression tree) does not replace reflection. – MarcinJuraszek Apr 04 '14 at 02:11
  • something like GetCustomAttributes(function(m) m) Then by using that method would return those properties that have Mask custom attribute. – Hatjhie Apr 04 '14 at 02:16
  • 4
    But you still have to use reflection to get these properties with custom attributes. – MarcinJuraszek Apr 04 '14 at 02:25
  • What I mean is similar with this: http://stackoverflow.com/questions/4276566/c-how-can-you-loop-over-the-properties-of-a-class Using Lambda Expression to loop through the properties. – Hatjhie Apr 04 '14 at 02:30
  • OK. It says about Expression Trees, and yes, you can create similar solution: use reflection to get necessary data only the first one your logic is invoked for given type, generate proper Expression Tree and compile it to lambda expression. Every next invocation for the same time would get performance comparable to standard .NET code you write and compile in front. But how to do that depends on what kind of stuff you want to do with these properties. – MarcinJuraszek Apr 04 '14 at 02:44
  • Yes, at the moment, I want to mask the properties values found that have the Mask Custom Attribute. But I don't know how to get: 1. Properties name that have Mask custom attribute. 2. Change the properties value found in point 1 to the mask value. – Hatjhie Apr 04 '14 at 02:57
  • 1
    You should probably start with implementation you'd write without reflection or expression tree. Just hardcoded list of properties. Then, you can try to dynamically get the properties and generate code using expression trees. It's always better to know how code you're trying to generate using expression tree would look like if you'd write it yourself, without expressions. – MarcinJuraszek Apr 04 '14 at 03:05
  • Yes, any sample codes? – Hatjhie Apr 04 '14 at 03:34
  • 1
    @Hatjhie, Marcin has given some good feedback on how to do what you need. It would bet better to try to do what Marcin suggests, then when you run into problems, post those particular issues. This seems too broad for a single question. The suggestion is from this: _use reflection to get necessary data only the first one your logic is invoked for given type, generate proper Expression Tree and compile it to lambda expression. Every next invocation for the same time would get performance comparable to standard .NET code you write and compile in front_ – SeraM May 07 '14 at 21:58
  • @Hatjhie, are you still interested in this answer? – Nizam Aug 12 '14 at 05:19
  • @Nizam, yes, I would try again later. Thanks for your info! – Hatjhie Aug 12 '14 at 10:27

1 Answers1

0

Use the following code to get a list with all property descriptors with the Mask attribute of the v object (the name you used in your example):

    Dim props As List(Of PropertyDescriptor) = (
                From C As PropertyDescriptor In TypeDescriptor.GetProperties(v.GetType)
                Where C.Attributes.OfType(Of MaskAttribute)().Count > 0
                Select C
    ).ToList

You need to import System.ComponentModel


Retrieving the property value

If you need the value of property, you can use the following code (Access property using its name in vb.net):

Public Function GetPropertyValue(ByVal obj As Object, ByVal PropName As String) As Object
    Dim objType As Type = obj.GetType()
    Dim pInfo As System.Reflection.PropertyInfo = objType.GetProperty(PropName)
    Dim PropValue As Object = pInfo.GetValue(obj, Reflection.BindingFlags.GetProperty, Nothing, Nothing, Nothing)
    Return PropValue
End Function

Observe that in our example, the name of property is given by the property Name of each PropertyDescriptor in the list props.


UPDATE

This would not work in your example because you have an object of car type inside other object of vehicle type, and I was not considering the inner object.

The way I found to work with this is using recursion:

Sub GetPropertiesWithMaskAttribute(Obj As Object, ByRef props As List(Of PropertyDescriptor))
    Dim props1 As List(Of PropertyDescriptor) = (From C As PropertyDescriptor In TypeDescriptor.GetProperties(Obj) Select C).ToList
    For Each prop In props1
        If prop.Attributes.OfType(Of MaskAttribute)().Count > 0 Then
            props.Add(prop)
        Else
            If prop.ComponentType.IsClass Then
                GetPropertiesWithMaskAttribute(GetPropertyValue(Obj, prop.Name), props)
            End If
        End If
    Next
End Sub

Calling like this:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim props As New List(Of PropertyDescriptor)
    GetPropertiesWithMaskAttribute(v, props)
End Sub

Then the props list will contains all properties with MaskAtribute attribute. Observe that I used the sub GetPropertyValue declared before.

Community
  • 1
  • 1
Nizam
  • 4,569
  • 3
  • 43
  • 60
  • Hey, thanks for your answer. I am looking to solve this using expression instead of reflection. Any idea? Thanks – Hatjhie Aug 18 '14 at 09:24