Cook Computing

InitializeLifetimeService Problem Solved

May 25, 2003 Written by Charles Cook

I've been experimenting with .NET leasing and I came across a problem. I wanted to configure the lease of an object from a factory class instead of overriding the InitializeLifetimeService method of the object's class. The latter technique is well documented and looks like this:


public class MyClass : MarshalByRefObject
{
  ...
  public override Object InitializeLifetimeService()
  {
    ILease lease = (ILease)base.InitializeLifetimeService();
    if (lease.CurrentState == LeaseState.Initial)
    {
      lease.InitialLeaseTime = TimeSpan.FromSeconds(10);
      lease.SponsorshipTimeout = TimeSpan.FromSeconds(10);
      lease.RenewOnCallTime = TimeSpan.FromSeconds(10);
    }
    return lease;
  }
  ...
}

My factory class is used to create objects of different types and instead of overriding InitializeLifetimeService in each of these classes I wanted to do something like the following:


public class TestClassFactory : MarshalByRefObject
{
  ...
  public object Create()
  {
    // in real code can create different types here
    object obj = new TestClass();
    ILease lease = (ILease)obj.InitializeLifetimeService();
    if (lease != null)
    {
      lease.InitialLeaseTime = TimeSpan.FromSeconds(10);
      lease.SponsorshipTimeout = TimeSpan.FromSeconds(10);
      lease.RenewOnCallTime = TimeSpan.FromSeconds(10);
    }
    return obj;
  }
  ...
}

Unfortunately this has the flaw that when the Remoting framework calls InitializeLifetimeService a different lease is returned and the above settings are ignored. The lease which is being initialized above must be returned in the framework's call to InitializeLifetimeService so we need to override InitializeLifetimeService so that the base class's version of the method is only called once:


public class MyClass : MarshalByRefObject
{
  ...
  public override Object InitializeLifetimeService()
  {
    if (_lease == null)
      _lease = (ILease)base.InitializeLifetimeService();
    return _lease;
  }
  ILease _lease;
  ...
}

This code can be factored out into an intermediate base class. All the types to be created by the factory class can then be derived from this class instead of MarshalRefObject which means they need not override InitializeLifetimeService:


public class MyBaseClass : MarshalByRefObject
{
  public override Object InitializeLifetimeService()
  {
    if (_lease == null)
      _lease = (ILease)base.InitializeLifetimeService();
    return _lease;
  }
  ILease _lease;
}

public class MyClass : MyBaseClass
{
  ...
}

public class MyOtherClass : MyBaseClass
{
  ...
}