plugin's and invalid cast.

D

Dan Bass

VB.Net app, but applies to the C# articles I've seen (from Mr Skeet for
example) so decided to cross post to glean some more wisdom...

I've two instances of the plugin framework in my app for two separate
interfaces. One works and one doesn't, and for the life of my I can't figure
out the difference between them.

The one that works just fine:
IClient is the interface
DefaultClient is an abstract class whose parent is IClient (both
DefaultClient and IClient exist in IClient.DLL)
FileClient is a concrete class whose parent is DefaultClient. (FileClient
exists in FileClient.DLL)

I call this function from another application that references IClient to
dynamically load the plugin FileClient into an IClient referenced variable,
but this method resides in a singleton in IClient.DLL

Public Function Load(ByVal nameOfClient As String) As IClient

Dim asm As Assembly = Assembly.LoadFrom(nameOfClient + ".dll")
Dim ts As Type() = asm.GetTypes()
Dim t As Type = asm.GetType(_parentNamespace + nameOfClient, False,
True)
If (Not t Is Nothing) Then
Dim client As IClient = CType(Activator.CreateInstance(t),
IClient)
Return client
Else
Return Nothing
End If

End Function


The one that doesn't:
ITransform is the interface
TransformToXml is an abstract class whose parent is ITransform (both
TransformToXml and ITransform exist in ITransform.DLL)
PTXTransform is a concrete class whose parent is TransformToXml
(PTXTransform exists in PTXTransform.DLL)

I call this function from the same 3rd party app that also references
ITransfer (as well as IClient), and also resides in a singleton in
ITransform.DLL. When it gets to "CType(Activator.CreateInstance(t),
ITransform)", it fails with Invalid cast exception...

Public Function Load(ByVal nameOfTransform As String) As ITransform

Dim asm As Assembly = Assembly.LoadFrom(nameOfTransform + ".dll")
Dim ts As Type() = asm.GetTypes()
Dim t As Type = asm.GetType(_parentNamespace + nameOfTransform,
False, True)
If (Not t Is Nothing) Then
Dim trans As ITransform = CType(Activator.CreateInstance(t),
ITransform)
Return trans
Else
Return Nothing
End If

End Function


Now what comes to mind is that IClient is only working as a fluke, and
ITransform truly reflects my error, or I'm just missing something so simple
that I need to be shot. Below is the relevant implementation for the
classes/interfaces mentioned.


ITRANSFORM.DLL -----------------------------------------------------------------------------

Public Interface ITransform

Sub Initialise(Optional ByVal configurationFile As String = "")
Function Transform(ByVal source As String) As String

End Interface

Public MustInherit Class TransformToXml
Implements ITransform

Public MustOverride Sub Initialise(Optional ByVal configurationFile As
String = "") Implements ITransform.Initialise
Public MustOverride Function Transform(ByVal source As String) As String
Implements ITransform.Transform

Protected Function CreateSubXmlNode(ByVal doc As XmlDocument, ByVal
elementName As String, Optional ByVal elementContent As String = "") As
XmlNode
...
End Function

Protected Function XmlDocToString(ByVal xmlDoc As XmlDocument) As String
...
End Function

End Class

PTXTRANSFORM.DLL -----------------------------------------------------------------------------

Public Class PTXTransform
Inherits Olympus.GrapeVine.Transform.TransformToXml

Public Overrides Sub Initialise(Optional ByVal configurationFile As
String = "")
End Sub

Public Overrides Function Transform(ByVal source As String) As String
...
End Function

Private Function DecodeAudit(ByVal source As String()) As String
...
End Function

Private Function DecodeJob(ByVal source As String()) As String
...
End Function

Private Function DecodeWindow(ByVal source As String()) As String
...
End Function

Private Function DecodeMonitor(ByVal source As String()) As String
...
End Function

End Class


ICLIENT.DLL -----------------------------------------------------------------------------

Public Interface IClient

Property ClientName() As String
Sub Initialise(ByVal clientName As String, ByVal connectionString As
String)
Sub SendMessage(ByVal message As String)
Sub ReceiveMessage(ByRef message As String)
Function SupportedConnectionFields() As String

End Interface

Public MustInherit Class DefaultClient
Implements IClient

Protected _clientName As String
Public Property ClientName() As String Implements IClient.ClientName
Get
Return _clientName
End Get
Set(ByVal value As String)
_clientName = value
End Set
End Property

Public MustOverride Sub Initialise(ByVal clientName As String, ByVal
connectionString As String) Implements IClient.Initialise
Public MustOverride Sub ReceiveMessage(ByRef message As String)
Implements IClient.ReceiveMessage
Public MustOverride Sub SendMessage(ByVal message As String) Implements
IClient.SendMessage
Public MustOverride Function SupportedConnectionFields() As String
Implements IClient.SupportedConnectionFields

End Class



FILECLIENT.DLL -----------------------------------------------------------------------------

Public Class FileClient
Inherits Olympus.GrapeVine.Client.DefaultClient

Public Overrides Sub Initialise(ByVal clientName As String, ByVal
connectionString As String)
...
End Sub

Public Overrides Sub ReceiveMessage(ByRef message As String)
...
End Sub

Public Overrides Sub SendMessage(ByVal message As String)
...
End Sub

Public Overrides Function SupportedConnectionFields() As String
...
End Function

End Class
 
J

Jon Skeet [C# MVP]

On Dec 5, 11:47 am, "Dan Bass" <[email protected]>
wrote:

Now what comes to mind is that IClient is only working as a fluke, and
ITransform truly reflects my error, or I'm just missing something so simple
that I need to be shot. Below is the relevant implementation for the
classes/interfaces mentioned.

1) Are the DLLs all in the same directory?
2) Could you post exactly what the contents of each DLL, as confirmed
with Reflector/ILDASM?

Jon
 
D

Dan Bass

Thanks for your help Jon.

The first thing I tried was to separate out the abstract class from its
parent interface into different DLL's. So in my 3 tiered system each level
had its own DLL. This then all worked fine.

Not sure why, or the details of why it doesn't work if they're together, but
maybe it'll help someone.

Cheers.
Dan.
 
B

Ben Voigt [C++ MVP]

Dan Bass said:
Thanks for your help Jon.

The first thing I tried was to separate out the abstract class from its
parent interface into different DLL's. So in my 3 tiered system each
level had its own DLL. This then all worked fine.

Not sure why, or the details of why it doesn't work if they're together,
but maybe it'll help someone.

I'd try iterating through t.GetInterfaces(), print them out, and also see if
they compare equal to typeof(ITransform)... not sure what the VB.Net
equivalent is for the C# typeof keyword.

I suspect two different interfaces with the same name.
 
D

Dan Bass

I'd try iterating through t.GetInterfaces(), print them out, and also see
if they compare equal to typeof(ITransform)... not sure what the VB.Net
equivalent is for the C# typeof keyword.

I suspect two different interfaces with the same name.

Yeah that was my initial thought when it first started happening and did
infact check the list returned from GetInterfaces. There was only one
ITransform interface in existent and it was referenced to the project.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top