Late Binding: Sharing Source Files <-> Casting Problem

J

John Lafrowda

Dear all,

here is a simple problem that I cannot overcome:
I'm trying to write a client/server application in Visual Basic .net. The
server is an executable (.exe) project, the clients are class library (.dll)
projects. The server loads the clients from their DLL-files at runtime using
reflection tools, such as:

ClientAssembly =
System.Reflection.Assembly.LoadFrom(Client_To_Load_File_Name)

In the next step, the server wants to get access to a class that is
integrated in every client. To integrate it, the class is shared by all
clients and the server on a source file basis, i.e. all clients and the
server link (not copy) to the source file. Furthermore, the root namespace
of all projects is set to "". If we call the common class "MyClass", the
server is able to gain access to a client's imported copy by calling

dim x as Object
x = ClientAssembly.CreateInstance("MyClass")

So far, this all works fine. Now, the server wants to finally cast the
resulting object to a "MyClass" object, as it knows this class by source
code:

dim y as MyClass
y = CType(x, MyClass)

The latter function, however, failes during runtime with a message that
there is no appropriate conversion between the types "MyClass" and
"MyClass".

Obviously (...I think...), the problem is related to the fact, that at
runtime both server and client have integrated their copy of the MyClass
source code into their assembly in binary format. Consequently, the .net
framework sees both versions as different types and does not find an
appropriate cast.

To get over the problem, I found only to unsatisfying solutions:
1. Compile the class definitions in another Class Library. Link server and
clients to the assembly of this class library instead of the source code. In
this case, all players access the same _binary_ representation of the class.
The problem with this solution is that I have to recompile this new, central
class library with every change.
2. I do not use the cast mechanisms but only work with objects of type
"Object". This works but source code appears to be less clear.

Now the question: Is there any method to share a file of source code that
contains structure/class definitions and is it somehow possible for an
assembly to access structure/class objects of other assemblies at runtime if
there is no reference given to these assemblies at compile time?

Thanks,

John
 
J

Jay B. Harlow [MVP - Outlook]

John,
clients and the server on a source file basis, i.e. all clients and the
There's the rub!

If you are sharing the source file, then each assembly has a distinct type,
hence the casting problem. You need share the assembly between the client &
server. Remember that a "Type" (a class, interface, structure) is known to
the CLR not just by the Class name itself. The Assembly, Version, and
Namespace & some other stuff are also used to create a fully qualified type
name.

For details on the "Fully Qualified Type Names" see:

http://msdn.microsoft.com/library/d...ml/cpconSpecifyingFullyQualifiedTypeNames.asp
Now the question: Is there any method to share a file of source code that
contains structure/class definitions and is it somehow possible for an
assembly to access structure/class objects of other assemblies at runtime if
there is no reference given to these assemblies at compile time?
"No reference" no, as you need to reference to get the definitions.

I would recommend option 3:

Use the Separated Interface Pattern:
http://www.martinfowler.com/eaaCatalog/separatedInterface.html
Which lends itself well to the Plugin Pattern:
http://www.martinfowler.com/eaaCatalog/plugin.html
In the next step, the server wants to get access to a class that is
integrated in every client. To integrate it, the class is shared by all
By Server (below) I mean the code that is implementing (producing) the
object, by Client I mean the code that is using (consuming) the object.
Which may be opposite of what you are stating, as it sounds like you are
implementing the Plugin pattern.

Define a Class library that Defines an Interface that is implemented by the
Server class. Both the Client & the Server reference this Class Library. The
client casts the server object to an variable of the Interface type. Note
this Class Library needs all the interfaces, structures, classes & Enums
that are used between the Client & the Server.

By Interface I mean a type defined with the Interface keyword.

' in the "interface" class library assembly
Public Interface MyInterface
Sub MyMethod()
End Interface

' in the "server" assembly
Public Class MyClass
Implements MyInterface

Public Sub MyMethod() Implements MyInterface.MyMethod
End Sub

End Class

' in the "client" assembly
ClientAssembly =
System.Reflection.Assembly.LoadFrom(Client_To_Load_File_Name)
dim x as Object
x = ClientAssembly.CreateInstance("MyClass")
Dim y as MyInterface
y = DirectCast(x, MyInterface)
y.MyMethod()

Matthew MacDonald's book "Microsoft Visual Basic.NET Programmer's Cookbook"
from MS Press, has an example of the above using Remoting.

Hope this helps
Jay
 
J

John Lafrowda

Dear Jay,

thanks for your advise. It basically underlines what I've already expected:
The assembly of a common library is the file to share definitions, not its
source code.
Just another question to get a more clear picture:
What is the difference between your "option 3" and my "option 1" (besides
the fact that I that in my description the clients are the plugins which
would be in a .net/COM view be the servers)?
I would recommend option 3:

Use the Separated Interface Pattern:
http://www.martinfowler.com/eaaCatalog/separatedInterface.html
Which lends itself well to the Plugin Pattern:
http://www.martinfowler.com/eaaCatalog/plugin.html

[...]
To get over the problem, I found only to unsatisfying solutions:
1. Compile the class definitions in another Class Library. Link server and
clients to the assembly of this class library instead of the source code.
In this case, all players access the same _binary_ representation of the
class.
The problem with this solution is that I have to recompile this new, central
class library with every change.


Best regards,

John
 
J

Jay B. Harlow [MVP - Outlook]

John,
In your option 1 you are binding to the classes (the implementation), if the
class changes you need to recompile the server. (remember the fully
qualified type name).

In my option 3 you are binding to the interface, the implementation is
independent of the interface, if the implementation changes you do not need
to recompile the server.

By "implementation changes" I mean bug fixes where you need to recompile the
existing assembly. Although the same holds true for replacing the
implementation with a completely different implementation.

Hope this helps
Jay

John Lafrowda said:
Dear Jay,

thanks for your advise. It basically underlines what I've already expected:
The assembly of a common library is the file to share definitions, not its
source code.
Just another question to get a more clear picture:
What is the difference between your "option 3" and my "option 1" (besides
the fact that I that in my description the clients are the plugins which
would be in a .net/COM view be the servers)?
I would recommend option 3:

Use the Separated Interface Pattern:
http://www.martinfowler.com/eaaCatalog/separatedInterface.html
Which lends itself well to the Plugin Pattern:
http://www.martinfowler.com/eaaCatalog/plugin.html

[...]
To get over the problem, I found only to unsatisfying solutions:
1. Compile the class definitions in another Class Library. Link server and
clients to the assembly of this class library instead of the source code.
In this case, all players access the same _binary_ representation of the
class.
The problem with this solution is that I have to recompile this new, central
class library with every change.


Best regards,

John
 
J

John Lafrowda

Alright, so in my case it's basically the same because in my case the
"class" is really an "interface" with the execption that all it's member
functions return a standard value and so I will use a class instead of an
interface here. The class can then be overriden completely or only partially
by other, specialised classes - which are the ones that I really want to
cast. This way, the "interface class" stays unchanged if any internals of
the derived classes change - much like a true interface.

The whole thing works beautifully with the only drawback that I have another
project for the "interface class".

One last question: Is it just my stupdity or does the .net framework not
update references if external assemblies (such as my "interface class" have
been modified? Is there no other way than removing the reference and adding
it again after the "interface project" has been updated?

Best regards,

John


Jay B. Harlow said:
John,
In your option 1 you are binding to the classes (the implementation), if the
class changes you need to recompile the server. (remember the fully
qualified type name).

In my option 3 you are binding to the interface, the implementation is
independent of the interface, if the implementation changes you do not need
to recompile the server.

By "implementation changes" I mean bug fixes where you need to recompile the
existing assembly. Although the same holds true for replacing the
implementation with a completely different implementation.

Hope this helps
Jay

John Lafrowda said:
Dear Jay,

thanks for your advise. It basically underlines what I've already expected:
The assembly of a common library is the file to share definitions, not its
source code.
Just another question to get a more clear picture:
What is the difference between your "option 3" and my "option 1" (besides
the fact that I that in my description the clients are the plugins which
would be in a .net/COM view be the servers)?
I would recommend option 3:

Use the Separated Interface Pattern:
http://www.martinfowler.com/eaaCatalog/separatedInterface.html
Which lends itself well to the Plugin Pattern:
http://www.martinfowler.com/eaaCatalog/plugin.html

[...]
To get over the problem, I found only to unsatisfying solutions:
1. Compile the class definitions in another Class Library. Link
server
and
clients to the assembly of this class library instead of the source code.
In this case, all players access the same _binary_ representation of the
class.
The problem with this solution is that I have to recompile this new, central
class library with every change.


Best regards,

John
 
J

Jay B. Harlow [MVP - Outlook]

John,
Alright, so in my case it's basically the same because in my case the
"class" is really an "interface" with the execption that all it's member
I would recommend you make the class MustInherit if you go the class route,
making it an Abstract Base Class. Making it MustInherit will prevent the
class from being instantiated.

One last question: Is it just my stupdity or does the .net framework not
update references if external assemblies (such as my "interface class" have
been modified? Is there no other way than removing the reference and adding
it again after the "interface project" has been updated?
You generally need to recompile dependent assemblies, I have yet to see
where you need to remove & re-add a referenced assembly. Which version of
the VS.NET are you using? Do you have a solution with multiple projects? Did
you reference the Project or the resultant assembly?

I find in solutions like this, its "best" to define a single Solution with
multiple projects, that you then reference the respective Project in VS.NET,
this way VS.NET will manage the build order properly.

If you reference assemblies, you need to be certain to set the Project
Dependencies correctly...

Hope this helps
Jay

John Lafrowda said:
Alright, so in my case it's basically the same because in my case the
"class" is really an "interface" with the execption that all it's member
functions return a standard value and so I will use a class instead of an
interface here. The class can then be overriden completely or only partially
by other, specialised classes - which are the ones that I really want to
cast. This way, the "interface class" stays unchanged if any internals of
the derived classes change - much like a true interface.

The whole thing works beautifully with the only drawback that I have another
project for the "interface class".

One last question: Is it just my stupdity or does the .net framework not
update references if external assemblies (such as my "interface class" have
been modified? Is there no other way than removing the reference and adding
it again after the "interface project" has been updated?

Best regards,

John


Jay B. Harlow said:
John,
In your option 1 you are binding to the classes (the implementation), if the
class changes you need to recompile the server. (remember the fully
qualified type name).

In my option 3 you are binding to the interface, the implementation is
independent of the interface, if the implementation changes you do not need
to recompile the server.

By "implementation changes" I mean bug fixes where you need to recompile the
existing assembly. Although the same holds true for replacing the
implementation with a completely different implementation.

Hope this helps
Jay

John Lafrowda said:
Dear Jay,

thanks for your advise. It basically underlines what I've already expected:
The assembly of a common library is the file to share definitions, not its
source code.
Just another question to get a more clear picture:
What is the difference between your "option 3" and my "option 1" (besides
the fact that I that in my description the clients are the plugins which
would be in a .net/COM view be the servers)?

I would recommend option 3:

Use the Separated Interface Pattern:
http://www.martinfowler.com/eaaCatalog/separatedInterface.html
Which lends itself well to the Plugin Pattern:
http://www.martinfowler.com/eaaCatalog/plugin.html

[...]

To get over the problem, I found only to unsatisfying solutions:
1. Compile the class definitions in another Class Library. Link server
and
clients to the assembly of this class library instead of the source
code.
In this case, all players access the same _binary_ representation
of
the
class.
The problem with this solution is that I have to recompile this new,
central
class library with every change.


Best regards,

John
 

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