Stashing Data in Extensible Objects

How do I store some
state about the current request so that I can use it later during the same service
operation?

There are several different standard contexts in which state
can be stored. Each of them works the same so I'll present all of them together
today.

- State that has the same lifetime as the service host lives inside the service host.

State that has the same lifetime as the current  
service instance lives inside the InstanceContext.
  • State that has the same lifetime as the current
    service operation lives in inside the OperationContext.

The mechanism for storing and retrieving this state is
IExtensionCollection<T>. There is an
IExtensionCollection<ServiceHostBase>, an
IExtensionCollection<InstanceContext>, and an
IExtensionCollection<OperationContext>. These three collection classes
are on the corresponding service classes as a member called Extensions. For
each IExtensionCollection<T>, you can define a new class that implements IExtension<T>
and contains whatever state data you want. You drop a state object into the
Extensions collection when you have something to record. When you want to
retrieve the state, you search the Extensions collection for an instance whose
type matches the one you created. Let's look at an example.

 class MyServiceState : IExtension<ServiceHostBase>
{
   public int ServiceCallCounter = 0;

   public void Attach(ServiceHostBase owner)
   {
   }

   public void Detach(ServiceHostBase owner)
   {
   }
}

Attach and Detach are called when the object is added to or
removed from the collection. The timing isn't always consistent here. Detach is
called before removal when removing a single item but after removal when
removing all items. Attach is always called before the item is added to the
collection.

I can then add my state to the service host at some point
after it's created.

 host.Extensions.Add(new MyServiceState());

Now, inside one of my service operations, I can fish out
this state and use it in some way.

 OperationContext.Current.Host.Extensions.Find<MyServiceState>().ServiceCallCounter++;

If I wanted the state to have a different lifetime, then I
would change the IExtension type and attach it to a different context object.

Next time: Table of Contents Scratch Work