There are two possible solutions here.
The Singleton approach: Override InitializeLifetimeService
As Sacha Goldshtein points out in the blog post linked to by the original poster, if your Marshaled object has Singleton semantics you can override InitializeLifetimeService
:
class MyMarshaledObject : MarshalByRefObject
{
public bool DoSomethingRemote()
{
// ... execute some code remotely ...
return true;
}
[SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.Infrastructure)]
public override object InitializeLifetimeService()
{
return null;
}
}
However, as user266748 points out in another answer
that solution wouldn't work if such an object were created each time a
client connects itself, because they would never be GCed and your
memory consumption would go up and up until either you stop your
server or it crashes because it has no more memory
The Class-Based approach: Using ClientSponsor
A more general solution is to use ClientSponsor
to extend the life of a class-activated remote object. The linked MSDN article has a useful starting example you can follow:
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Lifetime;
namespace RemotingSamples
{
class HelloClient
{
static void Main()
{
// Register a channel.
TcpChannel myChannel = new TcpChannel ();
ChannelServices.RegisterChannel(myChannel);
RemotingConfiguration.RegisterActivatedClientType(
typeof(HelloService),"tcp://localhost:8085/");
// Get the remote object.
HelloService myService = new HelloService();
// Get a sponsor for renewal of time.
ClientSponsor mySponsor = new ClientSponsor();
// Register the service with sponsor.
mySponsor.Register(myService);
// Set renewaltime.
mySponsor.RenewalTime = TimeSpan.FromMinutes(2);
// Renew the lease.
ILease myLease = (ILease)mySponsor.InitializeLifetimeService();
TimeSpan myTime = mySponsor.Renewal(myLease);
Console.WriteLine("Renewed time in minutes is " + myTime.Minutes.ToString());
// Call the remote method.
Console.WriteLine(myService.HelloMethod("World"));
// Unregister the channel.
mySponsor.Unregister(myService);
mySponsor.Close();
}
}
}
It is worth nothing how lifetime management works in the Remoting API, which is described quite well here on MSDN. I've quoted the part I found most useful:
The remoting lifetime service associates a lease with each service,
and deletes a service when its lease time expires. The lifetime
service can take on the function of a traditional distributed garbage
collector, and it also adjusts well when the numbers of clients per
server increases.
Each application domain contains a lease manager that is responsible
for controlling leases in its domain. All leases are examined
periodically for expired lease times. If a lease has expired, one or
more of the lease's sponsors are invoked and given the opportunity to
renew the lease. If none of the sponsors decides to renew the lease,
the lease manager removes the lease and the object can be collected by
the garbage collector. The lease manager maintains a lease list with
leases sorted by remaining lease time. The leases with the shortest
remaining time are stored at the top of the list. The remoting
lifetime service associates a lease with each service, and deletes a
service when its lease time expires.