1

I have a public subroutine that is called by many classes. However, I now need to do something in that subroutine that only pertains to a small number of the classes that call it. So instead of going back and adding the property to all of the existing classes, I would like to simply check to see see if that class has that property and if so, then do something with it. But I can't seem to figure out how to simply check for the existence of the member without getting an error.

For example:

Public Class_1

     Public a1 as string = ""

   Public Sub New()
       ' when a button is clicked call subroutine "check()"
   End Sub

End Class

Public Class_2

     Public a1 as string = ""
     Public a2 as integer = 0

   Public Sub New()
       ' when a button is clicked call subroutine "check()"
   End Sub

End Class

Public Class whatever

    Public Sub check(sender as object)
       If sender.a2 = 0 then
       ' do something
       End if
    End Sub

End Class

I have tried such things as

If not(sender.a2 is nothing) then
If isnothing(sender.a2) then

But I can't get past the fact that I get an error simply by using "sender.a2" since a2 is not always a member of the sender.

How can I check to see if a2 is a member of the sending class without using "sender.a2"?

John
  • 1,310
  • 3
  • 32
  • 58
  • 2
    OOP allows for overloaded methods. Rather than defining it as `Sub check(sender as object)` use the real types and define multiples. Inside you can call some common method, but it would allow the `Sub check(sender as Class_2)` to do `Class_2` specific things as needed. You can use reflection or gettype maybe to determine what you are working with, but it would be better to fix the code to be more OO. Inheritance or Interfaces might also solve it. – Ňɏssa Pøngjǣrdenlarp Jul 23 '15 at 14:46
  • possible duplicate of [Verify that an object has a certain property](http://stackoverflow.com/questions/9399872/verify-that-an-object-has-a-certain-property) – hubson bropa Jul 23 '15 at 14:46
  • 2
    You could create an interface what that property and implement that interface when the property is used. Then you just need to test and cast your object to that interface. Or if you put your check function inside your classes, you might not have this problem after all. – the_lotus Jul 23 '15 at 14:54

2 Answers2

3

If you want to see that a field exists you need this:

Dim fi As FieldInfo = sender.GetType().GetField("nameOfFieldHere")
If fi IsNot Nothing
   'field exists now get the value
    Dim o As Object = fi.GetValue(sender)
End If

Take a look at the documentation Type.GetField Method (String) There are also overloads available too.

Ric
  • 12,855
  • 3
  • 30
  • 36
  • It's not a field, it's a "member" as the error says "a2 is not a member of the class..." – John Jul 23 '15 at 14:53
  • It most definitely is a field. The issue is that sender is being passed as object that does not have this field. but the actual underlying object type (`Class_1` or `Class_2`) does hence the error. – Ric Jul 23 '15 at 14:54
  • 1
    Your close, but what I think I need is GetMember not GetField. – John Jul 23 '15 at 14:55
  • Well have you tried what I've suggested and verified it? I've created a sample app and it works. – Ric Jul 23 '15 at 14:56
  • Using "as FieldIno" gives me an error. What type is FieldIno? – John Jul 23 '15 at 15:00
  • It was a typing mistake, i've corrected it now. Should have been `FieldInfo` – Ric Jul 23 '15 at 15:01
1

You can test that the Object you are referencing is of a certain type before attempting to use it. Once you've determined it's the right type, you can safely cast to it and then use the right properties like so:

If (TypeOf sender Is Class_2) Then
  Dim castObj As Class_2 = CType(sender, Class_2)
  'We can now access castObj.a2
End If

If there are multiple classes with the property, it would be sensible to create an Interface which states they have the a2 property and have them all implement it. You can then test their type against the new Interface instead of Class_2.

An alternative option is to use class inheritance to implement a default public method for all classes, and override it in your special Class_2 case for your subclasses.

Wibbler
  • 1,020
  • 9
  • 17
  • But there are many classes that use this subroutine and I don't want to have to check to see which one is calling the sub. It would be a big list. – John Jul 23 '15 at 14:54
  • 1
    This is the reason you probably want to use something that ties all of the classes together, such as an interface or base class. – Ric Jul 23 '15 at 15:03
  • As @Ric said, you can just test against the interface which your subset of classes will be inheriting. This _should_ be more efficient than the reflection going on in Ric's answer and has the added advantage of being refactor-safe as you don't have a field name floating around in a string to remember to update. – Wibbler Jul 23 '15 at 15:39