1

In my application I have an Array of Objects, The type of all objects will be always same but unknown but I need to update one property of object of array based on some condition

I tried to implement the same like below using reflection

  Public Shared Sub FilterobjectArray(ByVal obj As Object())
     
            Dim r = obj.Where(Function(x) CStr(x.[GetType]().GetProperty("Id")?.GetValue(x)) = "2")

            For Each item In r
                Dim propertyInfo As PropertyInfo = item.[GetType]().GetProperty("CompanyName")
                propertyInfo.SetValue(item, Convert.ChangeType("MyCompany", propertyInfo.PropertyType), Nothing)
            Next           
    End Sub

Problem I think the Lambda expression for filtering the array is wrong as it throws "Object reference not set " in x

My sample implementation

Company Entity

Public Class Company
    Public Property Id As Integer
    Public Property CompanyName As String
End Class

Implementation

    Dim comp(2) As Object
    Dim comp1 = New Company With {.Id = 1, .CompanyName = "Comp1"}
    Dim comp2 = New Company With {.Id = 2, .CompanyName = "Comp2"}
    comp(0) = comp1
    comp(1) = comp2
    FilterobjectArray(comp)

Can Someone Suggest What is wrong ,C# answers or syntax is also welcome

NB: error appears after first iteration in for loop i.e. after first "propertyInfo.SetValue" completes and next iteration start

enter image description here

9
  • 3
    Why do you need to use reflection? Can't you simply use an interface instead? Commented Jan 12, 2021 at 7:49
  • Because we don't know the type of object , so to filter based on a property value we used reflection Commented Jan 12, 2021 at 7:50
  • 1
    You're not adding any of the items to the array. The array has three Nothing values when you pass it to FilterobjectArray. Commented Jan 12, 2021 at 7:54
  • 1
    I've used the Telerik Code converter to convert your VB code to C# and it does translate it to an array of Object with 3 slots. And none of them are set. Commented Jan 12, 2021 at 7:55
  • 2
    @SreenathGanga I'll repeat Peter's comment. Why don't you use an interface? If you know the name of the property, you know enough about the type already. You don't need reflection. At best, you need to filter for objects that don't implement the interface with, eg OfType<>() Commented Jan 12, 2021 at 8:22

2 Answers 2

2

Here's the code you need:

Sub Main
    Dim comp(1) As Object
    comp(0) = New Company With {.Id = 1, .CompanyName = "Comp1"}
    comp(1) = New Company With {.Id = 2, .CompanyName = "Comp2"}

    FilterobjectArray(comp)
End Sub

Public Shared Sub FilterobjectArray(ByVal obj As Object())
    Dim r = obj.Where(Function(x) CStr(x.[GetType]().GetProperty("Id")?.GetValue(x)) = "2")
    For Each item As Object In r
        Dim propertyInfo As PropertyInfo = item.[GetType]().GetProperty("CompanyName")
        propertyInfo.SetValue(item, Nothing)
    Next
End Sub

You need to add the elements to the array first. Most everything else was good, I just simplified the SetValue call.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks .. But it was not the issue, I had already done the array fill in actual code but forgot to add it in SO. Sorry , I had updated the question the error message is also added
The error shows up after first "propertyInfo.SetValue(item, Nothing) "
Thank..now i got your point after reading peter and caius
1

Unlike in C# where you declare the size of an array, when you declare an array in VB you specify the last valid index. This means an array declared as object(2) has 3 slots - 0 (arrays start from 0), 1 and 2. You've put 2 objects so the third slot is null.

You then ForEach which hits the third null slot, but there is a twist:

The error window is telling you x is nothing, x is the variable used in the LINQ query. The LINQ query does not run on the line where you say Where, it runs as soon as you use the variable r in the ForEach.. So it might look like it's the first item that is causing the error because the ForEach is exploding, but it's not: it's the fact that the LINQ execution (that will hit the error on the third slot) is delayed until you enumerate the results of the LINQ query. If you add a .ToList() call onto the end of your Where, then the code will crash before your ForEach..

Add another object to your array in index 2, reduce the array to an object(1) or provide some protection against x being Nothing if your system will encounter null objects naturally at run time

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.