Select to view content in your preferred language

How to achieve queryinterface behaviour in VB .NET?

1481
7
06-17-2010 10:16 AM
DuncanHornby
MVP Notable Contributor
All,

I've decided to post this question here as I think this is my best chance in getting an answer.  I've got VB .net 2005. I'm familiar with creating a class with properties and methods and can even use interfaces. I understand overloading and simple examples of inheritance. I would like to replicate a behaviour of ArcObjects that I come to love and know, the QueryInterface.  So first just look at the simple example below using ArcObjects.

' Retrieve a Polygon from a collection
Dim pPolygon as IPolygon
pPolygon = aCollection.Item(0)
Dim pArea as IArea
pArea = pPolygon 'QI
Msgbox pArea.Area


pArea could have been pointed to an Envelope or Ring not just a Polygon.  I've been playing around with VB .Net trying to create classes that behave in the same way. I'm not talking about ArcObjects now just some class that I imagined up. How do you create a Class that you can point to another class. Take another example if you create a pointer of type IFeatureLayer and point it to a Layer you can access the search cursor but this not a method of ILayer.

I was wondering if any of you hardcore coders had a trivial example of a VB .Net project that shows custom classes (nothing to do with ArcObjects) behaving this way?  Does VB .Net even allow you to develop objects this way?

Duncan
0 Kudos
7 Replies
AlexanderGray
Honored Contributor
The behaviour you are talking about sounds like polymorphism which is an object oriented concept.  This is acheived in ArcObjects using interfaces.  When you are querying interfaces between ILayer and IFeatureLayer you are still dealing with the same object (e.g. FeatureLayerClass instance.)  The interface is just a standard way of interacting with the class, also called a contract.  If you look at all the classes that implement ILayer, many of them do not implement IFeatureLayer.  Query interface between ILayer and IfeatureLayer for a GroupLayerClass would fail because IFeatureLayer is not implemented on that class.

You can do the same in VB.NET, you need to define your own interfaces, then implement those interfaces in your classes.  You can also do class inheritance with abstract classes (mustinherit) and inherit the class in derived classes.  Class inheritance works a little differently than interface implementation so I suggest you take a look at both.  Object Oriented design can help make better applications there are many books and articles about it geared specifically to the VB.NET language.
0 Kudos
KirkKuykendall
Deactivated User
Something I really like about .NET  (which VB6 lacks) is generics.

While generics are great, you cannot cast a list of IEnvelopes to a list of IGeometrys in .NET 3.5 (covariance).  Supposedly .NET 4.0 supports this, but I haven't tried it yet with arcobjects interfaces.
http://msdn.microsoft.com/en-us/library/dd799517.aspx


Public Sub Test()
        Dim list1 As List(Of IEnvelope) = New List(Of IEnvelope)()
        ' compile error
        Dim list2 As List(Of IGeometry) = CType(list1, List(Of IGeometry))
End Sub


Since there is no inheritance between IArea and IPolygon, even at 4.0 I don't think you'll be able to cast a List of IPolygons to a List of IEnvelopes.
0 Kudos
DuncanHornby
MVP Notable Contributor
First of all thanks for replying!

I will show you what I'm trying to do. Please note I use ArcObject names but this VB project has no reference to ESRI libraries! I just use them as I'm familiar with their true behaviour. I think this will help you understand what I'm trying to achieve.

I declare my interfaces and classes

Public Interface ILayer
    Property Name() As String
End Interface

Public Interface IFeatureLayer
    Inherits ILayer
End Interface

Public Class baseLayer
    Implements ILayer

    Private m_Name As String

    Public Property Name() As String Implements ILayer.Name
        Get
            Return m_Name
        End Get
        Set(ByVal value As String)
            m_Name = Name
        End Set
    End Property
End Class

Public Class Featurelayer
    Inherits baseLayer
End Class


I created a form, dropped a button on it and on the on click event I attempt to run the following code

Dim pLayer As ILayer
        pLayer = New baseLayer
        pLayer.Name = "Duncan"
        Dim pFeatureLayer As IFeatureLayer
        pFeatureLayer = pLayer '********** Invalid cast exception is thrown here.
        MsgBox(pFeatureLayer.Name)


What school boy error am I doing?

Duncan
0 Kudos
KirkKuykendall
Deactivated User
All featurelayers are baselayers, but not all baselayers are featureLayers.

so instead of this:
pLayer = New baseLayer
try this:
pLayer = New featureLayer

Also you should make featureLayer implement IFeatureLayer.
0 Kudos
DuncanHornby
MVP Notable Contributor
Kirk,

You star!  I did what you said and it works, you earned yourself a barrel of beer! Now I have this "trivial" example clear in my heard this will allow me to move on to tougher stuff.  I also did what you said and implemented IFeatureLayer in FeatureLayer and was surprised I did not have to wire up any code, can you explain this? My full code is below:

Class code:
Public Interface ILayer
    Property Name() As String
End Interface

Public Interface IFeatureLayer
    Inherits ILayer
End Interface

Public Class baseLayer
    Implements ILayer

    Private m_Name As String

    Public Sub New()
        m_Name = ""
    End Sub

    Public Property Name() As String Implements ILayer.Name
        Get
            Return m_Name
        End Get
        Set(ByVal value As String)
            m_Name = value
        End Set
    End Property
End Class

Public Class Featurelayer
    Inherits baseLayer
    Implements IFeatureLayer
End Class


My calling code:

Dim pLayer As ILayer
pLayer = New Featurelayer
pLayer.Name = "Kirk is awesome!"
Dim pFeatureLayer As IFeatureLayer
pFeatureLayer = pLayer
MsgBox(pFeatureLayer.Name)
0 Kudos
AlexanderGray
Honored Contributor
The Interface Ifeaturelayer doesn't have any properties or methods of its own.  Therefor the implementation of ILayer on your base layer is sufficient to implement IFeatureLayer on FeatureLayer.  Typically an interface inheritance is done to provide extra methods and properties.  If you add another property on IFeatureLayer, you will see what happens.
0 Kudos
DuncanHornby
MVP Notable Contributor
Alexander,

I added another property to IFeatureLayer and as you predicted I had to deal with the addition code, thanks. I feel I have genuinely expanded my understanding of how to get classes to behave similar to ArcObjects. So thanks for your help.

Duncan
0 Kudos