all groups > dotnet remoting > september 2005 >
You're in the

dotnet remoting

group:

HELP: pass object to client from a different appdomain


HELP: pass object to client from a different appdomain Hank
9/9/2005 7:36:11 PM
dotnet remoting:
I am writing a windows service application and multiple clients, they run on
the same machine.
I used SAO/CAO factory pattern, they worked fine if I "new" the server
object when client request it.
However I run into a problem when I tried to create new object and run on a
new appdomain, following is the situation:
Client:
reading configure file
getting a server side factory object
IRemoteObject = factory.CreateInstance();
IRemoteObject.GetValue(); //this line will fail and complaining about
not having channel and sink setup if I use appdomain approach.
.......

Server side:
read configur file and Factory object is registered as a singleton
class FactoryObject : MarshleByReference, IFactoryObject
{
.....
IRemoteObject CreateInstance()
{
Appdomain ad = Appdomain.CreateDomain("mydomain");
return (
(RemoteObject)ad.CreateInstanceAndUnWrap(.............) );
}
}

Server will work if I changed to
class FactoryObject:MarshleByReference, IFactoryObject
{
IRemoteObject CreateInstance()
{
return new RemoteObject();
}
}

But my design is to create a the server object and run on a differnt domain
each time a new client request to create
a new server object through Factory pattern.
Your help is highly appreciated!

Re: HELP: pass object to client from a different appdomain Robert Jordan
9/11/2005 8:24:26 PM
Hi Hank,

[quoted text, click to view]

You need to register a remoting channel in each domain.
Take care with Tcp and HttpChannels: the port numbers must
be different per domain.

Re: HELP: pass object to client from a different appdomain Hank
9/11/2005 10:32:53 PM
Rob,
Thanks for the suggestion, however I won't be able to know how many clients
will connect to the server, so the number of domains can't be determined in
advance. In other words, the domains need to be created dynamically.
My SAO/CAO design is to let server factory object register as IPC
channel(Singelton), each client calls the factory's createInstance method to
create another server object. it is this second server object needs to be
created in a new domain. However I can't predermine this second object's
channel unless I manually fix or limit the number of clients connecting to
the server, then I can register channel for each domain.
Hank

[quoted text, click to view]

Re: HELP: pass object to client from a different appdomain Robert Jordan
9/12/2005 10:06:51 AM
Hi Hank,

[quoted text, click to view]

Of course you can. What stops you to register the channels?
Do it the same way as for the first app domain.

If you don't register the channels in the domain, it simply
won't work.

Rob


[quoted text, click to view]
Re: HELP: pass object to client from a different appdomain Robert Jordan
9/12/2005 10:43:38 AM
[quoted text, click to view]

BTW, you don't register an IPC singleton channel. You register
a channel. On this channel you publish a Sigleton.

What you have to do on the *other* app domains: just
register an IPC channel with another distinct port name:

string portName = Guid.NewGuid().ToString();
ChannelServices.RegisterChannel(new IpcChannel(portName));

You don't need t publish the Singleton again!

Rob

[quoted text, click to view]
Re: HELP: pass object to client from a different appdomain Hank
9/12/2005 11:08:07 PM
Rob,
I tried following 2 ways based on your instruction, still doesn't work:
(Note: both client and server read from config file for intial Factory
object)
(Way 1) CLIENT side:
......
IRemoteFactory fact =
(IRemoteFactory)RemotingHelper.CreateProxy(typeof
(IRemoteFactory));
IRemoteObject iro = (IRemoteObject)Factory.CreateInstance();
IRemoteObject.GetValue;

SERVER side:
class RemoteObject : MarshalByReference, IRemoteObject
{
.....
}

classs RemoteFactory
{
.......
IRemoteObject CreateInstance()
{
AppDomain ad = AppDomain.CreateDomain("My second domain");
string portName = Guid.NewGuid().ToString();
ChannelServices.RegisterChannel(new IpcChannel(portName));
return ( (RemoteObject)ad.CreateInstanceAndUnWrap(....));
}
.......
}

Server side I got error says: The channel 'ipc' is already registered.
This is because in the server side configuration file, the initial
RemoteFactory object is registed by 'ipc'

(Way 2)CLIENT side:
no code change
SERVER side
add following line under "ChannelServices.RegisterChannel(new
IpcChannel(...))":
RemotingConfiguration.RegisterWellKnowServiceType(
typeof(RemoteObject), "RemoteObject.rem",
WellKnowObjectMode.Singleton);

the rest of the server code are same.

Server side I got the same error as in (1)

QUESTIONS:
(1)do I miss anything here, looks like I can't create second IPC channel in
server since the first one is already created in the server config file. the
server side config file looks like following
....
<application>
...
<service>
<wellknown type="General.RemoteFactory, MyFactoryAssemble"
objectUri="RemoteFactory.rem"
mode="Singleton" />
</service>
<channels>
<channel ref="ipc" portName="MyFirstPort" />
</channels>
...
</application>
....
client side has a corresponding config file.

(2)at client side, I don't know anything about RemoteObject with newly
created "protName" by server?
this might be a stupid question:
at client side do I need to register the RemoteObject with portName? if
yes how the server pass the created "portName" to client?

(3) since the RemoteObject instance(reference?) is created by second
appdomain, however the channel registration is still in the first domain,
could that be the problem?

Thanks!
Hang


[quoted text, click to view]

Re: HELP: pass object to client from a different appdomain Robert Jordan
9/13/2005 12:00:00 AM
Hank,

[quoted text, click to view]

The are probably a lot of solutions. One of them is:
"execute" the assembly in the new domain:

In your server

public class Server : MarshalByRefObject, IServerApi
{
public IFooObject CreateFooObject ()
{
AppDomain d = AppDomain.CreateDomain ("Foo");
d.ExecuteAssembly ("server.exe", null, new string[]
{"/domain"});
FooObject f = (FooObject) d.CreateInstanceAndUnwrap
("server", "ACME.FooObject");
return f;
}
}


in your Main-method:


public static void Main(string[] args) {
if (args.Length > 0 && args[0] == "/domain") {
// new domain
// register the channel
ChannelServices.RegisterChannel ( ....);
}
else {
// first domain
// do the usual configuration
RemotingConfiguration.Configure(.....);
}
}


[quoted text, click to view]

Yoo don't need.

Re: HELP: pass object to client from a different appdomain Hank
9/13/2005 10:17:36 AM
Rob,
Thanks for advising, now the idea is clear, i need call RegisterChannel in
the new appdomain, but the questions are:
(1)How to call "ChannelServices.RegisterChannel(new IpcChannel(portName))"
through the "ad" reference or some other mechanism such as event, could you
give me a very brief code snippet?
(2)How to let client know there is a new channel registered OR do I need to
let client know?
Thanks
Hank
[quoted text, click to view]

Re: HELP: pass object to client from a different appdomain Robert Jordan
9/13/2005 11:14:25 AM
Hi Hank,

[quoted text, click to view]

You must call RegisterChannel in the new appdomain.

Re: HELP: pass object to client from a different appdomain Hank
9/13/2005 2:56:16 PM
Rob,
It all worked out nicely. Thanks for all the help!
Hank

[quoted text, click to view]

Re: HELP: pass object to client from a different appdomain Robert Jordan
9/13/2005 10:06:37 PM
Hi Hank,

[quoted text, click to view]

You're welcome!

AddThis Social Bookmark Button