.NET provides managed classes with an easy way to hook up a server that fires events with client sinks. The .NET mechanism is certainly an improvement over the somewhat cumbersome COM connection point protocol, but the .NET mechanism still suffers from all the disadvantages of tightly coupled events, as explained at the beginning of Chapter 9. Fortunately, managed classes can easily take advantage of COM+ loosely coupled events.
The EventClass
attribute is used to mark a serviced
component as a COM+ event class, as shown in Example 10-17.
Example 10-17. Designating a serviced component as an event class using the EventClass attribute
public interface IMySink
{
void OnEvent1( );
void OnEvent2( );
}
[EventClass
]
public class MyEventClass : ServicedComponent,IMySink
{
public void OnEvent1( )
{
throw(new NotImplementedException(exception));
}
public void OnEvent2( )
{
throw(new NotImplementedException(exception));
}
const string exception = @"You should not call an event class directly.
Register this assembly using RegSvcs /reconfig";
}
The event class implements a set of sink interfaces you want to publish events on. Note that it is pointless to have any implementation of the sink interface methods in the event class, as the event class’s code is never used. It is used only as a template, so that COM+ could synthesize an implementation, as explained in Chapter 9 (compare Example 10-17 with Example 9-1). This is why the code in Example 10-17 throws an exception if anybody tries to actually call the methods (maybe as a result of removing the event class from the Component Services Explorer).
When you register the assembly with COM+, the event class is added as a COM+ event class, not as a regular COM+ component. Any managed class (not just serviced components) can publish events. Any managed class can also implement the sink’s interfaces, subscribe, and receive the events. For example, to publish events using the event class from Example 10-17, a managed publisher would write:
IMySink sink; sink = (IMySink)new MyEventClass( ); sink.OnEvent1( );
The OnEvent1( )
method returns once all
subscribers have been notified, as explained in Chapter 9.
Persistent subscriptions are managed directly via the Component Services Explorer because adding a persistent subscription is a deployment-specific activity. Transient subscriptions are managed in your code, similar to COM+ transient subscribers.
The EventClass
attribute has two public Boolean
properties you can set, called
AllowInprocSubscribers
and
FireInParallel
. These two
properties correspond to the Fire in parallel and Allow
in-process subscribers, respectively, on
the event class’s Advanced tab. You can configure these values
on the event class definition:
[EventClass(AllowInprocSubscribers = true,FireInParallel=true)] public class MyEventClass : ServicedComponent,IMySink {...}
The EventClass
attribute has an overloaded default
constructor. If you do not specify a value for the
AllowInprocSubscribers
and
FireInParallel
properties, it sets them to
true
and false
, respectively.
Consequently, the following two statements
are equivalent:
EventClass] [EventClass(AllowInprocSubscribers = true,FireInParallel=false)]