.NET managed components can use COM+ JITA to efficiently handle rich clients (such as .NET Windows Forms clients), as discussed in Chapter 3.
To enable JITA support for your component, use the
JustInTimeActivation
attribute:
[JustInTimeActivation(true)] public class MyComponent :ServicedComponent {..}
When you register this component with COM+, the JITA checkbox in the
Activation tab on the Component Services Explorer is selected. If you
do not use the JustInTimeActivation
attribute,
JITA support is disabled when you register your component with COM+
(unlike the COM+ default of enabling JITA). The
JustInTimeActivation
class default constructor
enables JITA support, so the following two statements are equivalent:
[JustInTimeActivation] [JustInTimeActivation (true)]
Enabling JITA support is just one thing you need
to do to use JITA. You still have to let COM+ know when to deactivate
your object. You can deactivate the object by setting the
done bit in the context object, using the
DeactivateOnReturn
property of the
ContextUtil
class. As discussed at length in Chapter 3, a JITA object should retrieve its state at
the beginning of every method call and save it at the end. Example 10-3 shows a serviced component using JITA.
Example 10-3. A serviced component using JITA
public interface IMyInterface { void MyMethod(long objectIdentifier); } [JustInTimeActivation(true)] public class MyComponent :ServicedComponent,IMyInterface { public void MyMethod(long objectIdentifier) { GetState(objectIdentifier); DoWork( ); SaveState(objectIdentifier); //inform COM+ to deactivate the object upon method return ContextUtil.DeactivateOnReturn = true; } //other methods protected void GetState(long objectIdentifier){...} protected void DoWork( ){...} protected void SaveState(long objectIdentifier){...} }
You can also use the Component Services Explorer to configure
the
method
to use auto-deactivation. In that case, the object is deactivated
automatically upon method return, unless you set the value of
the DeactivateOnReturn
property to
false
.
If
your
serviced
component uses object pooling or JITA (or both), it may also need to
know when it is placed in a COM+ context to do
context-specific initialization and
cleanup. Like a COM+ configured component, the serviced component can
use IObjectControl
for that purpose. The .NET base
class
ServicedComponent
already implements
IObjectControl
, and its implementation is
virtual—so you can override the implementation in your serviced
component, as shown
in Example 10-4.
Example 10-4. A serviced component overriding the ServicedComponent implementation of IObjectControl
public class MyComponent :ServicedComponent { publicoverride
void Activate( ) { //Do context specific initialization here } publicoverride
void Deactivate( ) { //Do context specific cleanup here } publicoverride
bool CanBePooled( ) { return true; } //other methods }
If you encounter an error during Activate( )
and
throw an exception, then the object’s activation fails and the
client is given an opportunity to catch the exception.
To maintain JITA semantics, when the object deactivates itself, .NET
calls DisposeObject( )
on it explicitly, thus destroying it. Your object can do specific
cleanup in the Finalize( )
method (the destructor in C#), and Finalize( )
will be called as soon as the object deactivates itself, without
waiting for garbage collection. If the object is a pooled object (as
well as a JITA object), then it is returned to the pool after
deactivation, without waiting for the garbage collection.
You can also override the ServicedComponent
implementation of IObjectControl.Deactivate( )
and
perform your cleanup there.
In
any case, you end up with a deterministic
way to dispose of critical resources without explicit client
participations. This situation makes sharing your object among
clients much easier because now the clients do not have to coordinate
who is responsible for calling Dispose( )
.