Casting an object as an Interface that it implements

J

Jeff Molby

First off, this is a VB application, but I know you C# are used to working
at the lower levels like this, so I'm hoping this is an easy one for you.
Then you can continue to feel superior to us VB-types <G> BTW, I am somewhat
proficient in C#, but my bosses and coworkers barely know VB, so no, I can't
just rewrite it in C# <g>

Ok, I've googled long and hard, but I can't find anything relevant on this
one. I am now at the mercy of your good nature. <g>

I have 3 projects in my solution: One app and 2 libraries.

I am basically attempting to create a "plug-in" feature for my app.

Namespace A contains the plug-in interface
Namespace B is a sample implementation of that interface.
The application needs to be able to load the implementation in Namespace B
and use it via the interface.

Line 10 is where I create an instance of class BWInventory
Line 20 is where I get the following error when I try to get a reference to
the Interface

"An unhandled exception of type 'System.InvalidCastException' occurred in
BookWorks.exe
Additional Information: Specified cast is not valid"

I can continue to use it as an "object" and I can even call the interface
methods, but for various reasons, I need to have a real reference to the
interface.


Help! Thanks!
Jeff

Namespace A ' DLL. referenced by App and B
Public Interface IBWModule
ReadOnly Property Name() As String
End Interface
End Namespace

Namespace B 'Loaded dynamically by App
Public Class BWInventory
Implements IBWModule

Public ReadOnly Property Name() As String Implements
BookWorksCommon.IBWModule.Name
Get
Return "BookWorks Inventory"
End Get
End Property
End Class
End Namespace

Namespace App 'References A and dynamically loads B.
Imports BookWorksCommon
Public Class frmMain
Inherits System.Windows.Forms.Form
Dim WithEvents mfrmLogin As frmLogin
Dim colModules As Collection
Dim intCurrentModuleIndex As Integer

Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Dim PluginAssembly As System.Reflection.Assembly
Dim CommonAssembly As System.Reflection.Assembly
Dim t As Type
Dim i As Type
Dim x As Object 'IBWModule
Dim w As IBWModule
Dim typModule As Type

PluginAssembly =
System.Reflection.Assembly.LoadFrom("C:\Documents and Settings\mjozwik_2\My
Documents\Visual Studio
Projects\BookWorks\BookWorksInventory\bin\BookWorksInventory.dll")
CommonAssembly =
System.Reflection.Assembly.LoadFrom("C:\Documents and Settings\mjozwik_2\My
Documents\Visual Studio
Projects\BookWorks\BookWorksCommon\bin\BookWorksCommon.dll")

typModule = CommonAssembly.GetType("BookWorksCommon.IBWModule")
colModules = New Collection

For Each t In PluginAssembly.GetTypes
For Each i In t.GetInterfaces
If i.Equals(typModule) Then
10 x = Activator.CreateInstance(t)
colModules.Add(x)
20 w = CType(x,IBWModule)
End If
Next
Next
End Sub
End Class
End Namespace
 
J

Jon Skeet

Jeff Molby said:
First off, this is a VB application, but I know you C# are used to working
at the lower levels like this, so I'm hoping this is an easy one for you.
Then you can continue to feel superior to us VB-types <G> BTW, I am somewhat
proficient in C#, but my bosses and coworkers barely know VB, so no, I can't
just rewrite it in C# <g>

Ok, I've googled long and hard, but I can't find anything relevant on this
one. I am now at the mercy of your good nature. <g>

I have 3 projects in my solution: One app and 2 libraries.

I suspect the problem you've got is the one I've described here:
http://www.pobox.com/~skeet/csharp/plugin.html
 
J

Jon Skeet

Jeff Molby said:
First off, this is a VB application, but I know you C# are used to working
at the lower levels like this, so I'm hoping this is an easy one for you.
Then you can continue to feel superior to us VB-types <G> BTW, I am somewhat
proficient in C#, but my bosses and coworkers barely know VB, so no, I can't
just rewrite it in C# <g>

Ok, I've googled long and hard, but I can't find anything relevant on this
one. I am now at the mercy of your good nature. <g>

CommonAssembly =
System.Reflection.Assembly.LoadFrom("C:\Documents and Settings\mjozwik_2\My
Documents\Visual Studio
Projects\BookWorks\BookWorksCommon\bin\BookWorksCommon.dll")

I don't think you should load the common assembly by reflection - just
use the VB.NET equivalent of the C# "typeof" operator to get the common
type and cast to that.

I *think* that's probably the problem, but I wouldn't like to say for
sure.
 
J

Jeff Molby

I just found it. Somewhat of a variation on what you described in your site.

Because the IDE doesn't copy the DLL to my main app's bin directory (there's
no static reference), I was just loading the DLL from its own bin directory.
However, That directory had its own copy of the Interface assembly, so it
behaved just as you described in your site.

Sorry about the stupid mistake and thank you for your help!
 
J

Jeff Molby

I tried that, but VB's equivalent TypeOf statement can only be used in an If
statement and it can only compare against a hardcoded type, rather than type
object. It sucks...
 

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