all groups > dotnet remoting > june 2004 >
You're in the

dotnet remoting

group:

Generic deserialization


Generic deserialization Lee Gillie
6/29/2004 4:07:29 PM
dotnet remoting:
Trying to create a "generic" notification facility. Basically I have a
number of services which currently use NT MAILSLOTS to broadcast their
in-progress status to desktops on the LAN. In the mailslot there is
usually complex delimited data as a string.

My .NET approach is to instead use a "message server service". Also
attempting to provide a component that will make either SOURCE or
CONSUMER objects. The SOURCE object has one simple "Send" method, and
accepts a parameter of type "Object". Am making a "Consumer" object
which posts an event, and again, a single parameter of type OBJECT. I
am attempting to hide all the infrastructure and remoting as much as
possible, from the caller of the component. The component is also
exposing a COM interface. The component makes either a source or
consumer conversation with the service via one single remoted
component, which can "broadcast" events to clients. All of this works
great when the notify parameter is a string. But falls flat when
trying to do this with an item of type OBJECT.

Here is my extreme lack of knowledge about serialization...

Via the remoting method, I was able to send from a SOURCE to the
server, and it makes it back to the CONSUMER in a separate process.
But the consumer is having trouble looking at the "object". I get
this:

Run-time exception thrown :
System.Runtime.Remoting.RemotingException - This remoting proxy has no
channel sink which means either the server has no registered server
channels that are listening, or this application has no suitable
client channel to talk to the server.

The "object" being sent through this system is a "class" using only
fundamental data types, such as string, integer, and so on. The class
is marked serializable, and I found a need to inherit from MarshaByRef
to get the send side to work.

My thought is that once I get this class instance serialized, it is
completely self contained. Yet the message seems to indciate the
CONSUMER is somehow trying to get back to some remoting host, or such.
Probably due to the MBR.

Any hints on preparing my generic "object" parameter to be fully
self-sufficient would be greatly appreciated. In my component I don't
have knowledge of my caller's classes. If I can, I would like to not
burden my caller to perform serialization and deserialization, if
possible.


Can what I am trying to do even be done?


Re: Generic deserialization Ken Kolda
6/29/2004 5:36:20 PM
The error you're getting is, as you suspected, due to the fact that your
class derives from MarshalByRefObject. When the consumer gets the reference
to this object and attempts to invoke one of its methods, it must open a
remoting channel back to the source, since that's where the object actually
resides. In this way, your "source" application acts as both client and
server. That's not a problem, but it sounds like that's not the model you're
trying to create.

The issue is that you indicated that you don't your message server service
to know about the client's classes. If you mark your classes as Serializable
but not MBR, then the server must generally have the implementation
available for the class, since the clss will be deserialized on the server.
But, assuming your server service has no need to ever know what the
underlying object is (i.e. it just passes it to a consumer which DOES know
what type of object this is), you could do something like this:

Create two wrapper classes in a separate assembly than from your remoted
server service classes, call them SourceWrapper and ConsumerWrapper. The
SourceWrapper would look something like:

class SourceWrapper
{
public SourceWrapper(string serverUri)
{ // Save off Uri to instance variable }

public void Send(object o)
{
// Serialize object using BinaryFormatter to get byte array
// Call Activator.GetObject() to get the remoted Source object from
server
// Invoke Source object's Send(), passing the bytes.
}
}

The ConsumerWrapper would, conversely look like:

class ConsumerWrapper : MarshalByRefObject
{
public event MessageArrivedEventHandler MessageArrived;

public ConsumerWrapper(string serverUri)
{
// Get the Consumer object from server and add an event handler or
callback for this instance
}

private onMessageArrived(byte[] data)
{
// Deserialize object using Binary formatter
// Raise MessageArrived event for client to be notified
}
}

In other words, the SourceWrapper handles the serialization and the
ConsumerWrapper handles the deserialization so the client app doesn't have
to worry itself about how this works. The server service in between knows
nothing except how to pass byte arrays around, so it's completely generic.

Hope that helps -
Ken


[quoted text, click to view]

Re: Generic deserialization Lee Gillie
6/30/2004 8:31:52 AM
VERY helpful Ken!!! I greatly appreciate your taking time to teach
this old dog some new tricks.

Best regards - Lee Gillie - Spokane, WA

[quoted text, click to view]

AddThis Social Bookmark Button