Subscription Types

As I mentioned earlier in the chapter, there are two types of subscribers. The first type is an existing instance of a class that supports a sink interface. That instance can be added at runtime to the list of subscribers of a particular event class. This type of subscription is called transient subscription because it exists as long as the subscriber is running and will not persist or survive a system reboot or a crash.

Note that when a particular instance of a class subscribes to an event class, only that instance will receive events published using that class. Other instances will receive the events only if they transiently subscribe themselves.

Adding a transient subscription can only be done programmatically using theCOM+ Catalog interfaces and objects. There is no administrative Component Services Explorer support. On the other hand, since all you give the COM+ Catalog is a pointer to a sink, even a nonconfigured COM component can register as a transient subscription, as long as it supports the sink interface.

Tip

A transient subscription does not even need to be on a Windows 2000 machine, as long as it is registered with a COM+ Catalog on the Windows 2000 machine where the event class resides.

The second type of subscription is used when you want COM+ to instantiate an object of a particular class when an event is published, let it handle the event, and release it. This type of subscription is called persistent subscription. Every event class has a list of persistent subscribers associated with it, stored in the COM+ Catalog. Persistent subscriptions, as the name implies, persist in the COM+ Catalog and survive a system restart.

Objects created by a persistent subscription are always released after each event delivery, even if more events are on the way. As a result, your subscribing component should be written to handle each event independently of other events that may or may not be published or delivered.

Adding a Persistent Subscription

Every component in the Component Services Explorer has a Subscription folder, containing the persistent subscriptions the product administrator or developer has set up. Every subscription represents an event class (or a list of event classes) that the component should be instantiated to receive events from whenever any publisher uses those event classes.

To add a persistent subscription, expand the subscription folder, right-click on it and select New from the pop-up context menu. This action invokes the New Subscription Wizard (see Figure 9-5).

The New Subscription Wizard

Figure 9-5.  The New Subscription Wizard

The New Subscription Wizard lets you subscribe to events published to all the sink interfaces your class supports, to a particular interface, or even just to a particular method. The wizard displays all the interfaces your component supports, including nonsink interfaces—COM+ doesn’t know whether they are sinks or not; only you know.

You can set up a subscription at the method or interface level. At the method level, COM+ delivers the event to your component only when publishers use that method. If you want to subscribe to another method, you have to add a new subscription.

A subscription at the interface level means that any event targeting any method on that interface should be delivered to your component. By providing you with these two options, you have the ability to subscribe to only a subset of the events publishers can publish or to all of them.

After you select the interfaces and methods, the wizard displays a list of all installed event classes that support the interfaces you selected in the previous steps. You can select a particular event class or all of them. The last step in the wizard lets you name the subscription and enable it. You can always enable or disable a subscription by highlighting it in the Subscriptions folder, displaying its properties page, selecting the Options tab, and enabling or disabling the subscription (see Figure 9-6).

A persistent subscription’s Options tab

Figure 9-6.  A persistent subscription’s Options tab

Adding a Transient Subscription

The only way to receive events on an already running object is to use transient subscription. Unlike persistent subscription, there is no administrative way to add a transient subscription. You have to program against the COM+ Catalog using the catalog objects and interfaces discussed in Chapter 6. In addition, it is your responsibility to remove the transient subscription from the Catalog when the subscribing component is released or if you want to unsubscribe.

Like a persistent subscriber, the object has to implement a sink interface for receiving events. The transient subscriber can choose to subscribe to all the sinks a particular event class supports, to a particular interface, or even to a particular method on a particular interface.

To add a transient subscription, you must follow these steps:

  1. Create the catalog object (CLSID_COMAdminCatalog ) and get a pointer to ICOMAdminCatalog.

  2. Call ICOMAdminCatalog::GetCollection( ) to retrieve a collection called TransientSubscription and get back an ICatalogCollection interface pointer.

  3. Call ICatalogCollection::Add( ) to get ICatalogObject .

  4. Call ICatalogObject::put_Value( ) once for each desired property of the transient subscription you want to set. Some examples are the event class you want to subscribe to, subscribing interfaces, and the subscription name. An important property you need to set is whether or not you want to enable the subscription.

  5. Call ICatalogCollection::SaveChanges( ).

  6. Release everything.

You are required to perform a similar sequence to remove the transient subscription.

In fact, as you will see later on, managing a transient subscription is not the only feature of COM+ events that requires programming against the COM+ Catalog: implementing, adding, and removing a publisher filter and transient subscriptions filtering are also only available programmatically. In all these cases, the developer is required to program against the Catalog interfaces.

The Catalog interfaces have the following limitations:

  • They are not type safe:

    • A BSTR is used for representing GUID, IID, and CLSID.

    • A BSTR is used instead of normal string.

    • Amorphous Variants are used to represent many data types.

  • The COM+ interfaces and the underlying programming model and objects hierarchy require tons of generic code for iterating over the Catalog, even for simple tasks.

  • The resulting code is tedious and error prone.

To alleviate the situation, I developed an easy-to-use wrapper object around the COM+ Catalog. The wrapper object saves you the agony of programming directly against the Catalog, reducing hundreds of lines of code to a mere line or two.

The wrapper object encapsulates the catalog objects and interfaces, exposing instead simple custom interfaces (with type safety) that perform all the hard work for you (see Figure 9-7). The wrapper object interfaces provide one-stop shopping for easy management of transient subscriptions and publisher filtering, providing you the same functionality as the Catalog interfaces with a fraction of the code.

The Catalog wrapper helper object

Figure 9-7.  The Catalog wrapper helper object

In the rest of this chapter, the use of the wrapper object will be demonstrated. Its implementation will also be described. The wrapper object source files are available on this book’s web site, http://oreilly.com/catalog/comdotnetsvs/.

The first thing you will use the wrapper object for is registering a transient subscription with the COM+ Catalog. The Catalog wrapper encapsulates the code required to register a transient subscription by exposing the ITransientSubscription interface, defined as:

interface ITransientSubscription : IUnknown
{
   HRESULT Add([in,string]LPCWSTR pwzName,[in]CLSID clsidEventClass,
               [in]REFIID iidInterface,[in]IUnknown *pSink);
   HRESULT Remove([in,string]LPCWSTR pwzName);

   HRESULT AddFilter([in,string]LPCWSTR pwzSubName,
                     [in,string]LPCWSTR pwzCriteria);
   HRESULT RemoveFilter([in,string]LPCWSTR pwzSubName);
};

ITransientSubscription provides you with everything you need to easily manage a transient subscription—you can add a subscription to all the interfaces of a specified event class or to a particular interface on that class. Later, you will use ITransientSubscription to install or remove a transient subscriber-side filter.

Adding a transient subscription using the helper object is a one liner—a vastly simplified programming model that completely encapsulates the underlying Catalog. After initializing a pointer to a sink (pMySink) that you want to receive events on, create the wrapper object using CLSID_CatalogWrapper and call TransientSubscription::Add( ):

//Creating the wrapper object:
ITransientSubscription* pTransSubs = NULL;


::CoCreateInstance(CLSID_CatalogWrapper,...,IID_ITransientSubscription,
                   (void**)&pTransSubs);

//Adding a transient subscription:
pTransSubs ->Add(L"My Subs",CLSID_MyEventClass,
                  IID_NULL,//All interfaces of the event class 
                  pMySink);

//When you wish to unsubscribe:
pTransSubs ->Remove(L"My Subs");

//Releasing the wrapper object:
pTransSubs ->Release(  );

When you add a subscription, you provide the Catalog wrapper with the subscription name—a string identifying the subscription. The name is used to identify the subscription when you want to remove it later or when you want to associate a filter with it.

Transient subscriptions are more efficient than persistent subscriptions because they do not require you to pay the overhead of creating the object. However, transient subscriptions raise some lifetime issues of classic COM tightly-coupled events. Another deficiency of transient subscriptions is that the party adding them has to have administrative privileges to modify the Catalog.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset