Section 11.1. .NET Component Services


11.1. .NET Component Services

.NET provides component services via call interception. To intercept a call, .NET must insert a proxy between the client and the object and do some pre- and post-call processing. Call interception is the key to valuable, productivity-oriented component services. For example, interception can provide thread safety by trying to acquire a lock before accessing the object and then proceeding to call the object. While the call is in progress, calls coming in from other clients are intercepted as well, and those calls will be blocked when they try to access the lock. When the call returns from the object to the proxy, it unlocks the lock to allow other clients to use the object. Another example of an interception-based component service is call authorization: the proxy can verify that the caller has appropriate credentials (such as being a member of a specified role) to call the object, and deny access if it does not. The problem with call interception is that an app domain is too coarse an execution scope; even though cross-app domain calls always go through a proxy, some app domain calls use direct references. To address this problem, app domains are further subdivided into contexts, and objects execute in contexts rather than app domains (see Figure 11-1).

Figure 11-1. App domains and contexts


In .NET, the context is the innermost execution scope of an object. Components indicate to .NET which services they require using special context attributes. All objects in the same context are compatible in terms of their component services requirements, and .NET doesn't need to perform pre- and post-call processing when these objects access one another. You can, therefore, define a context as a logical grouping of objects that rely on the same set of services. Calls into the context are intercepted to ensure that the objects always get the appropriate runtime environment they require to operate.

11.1.1. Contexts and Object Types

What if a component doesn't require any services? Why should it pay the interception penalty for cross-context access? To address this point, .NET objects are classified into two categories: those that care about component services and want to use them, and those that don't. By default, objects are context-agnostic and have no context affinity, which means they always execute in the contexts of their calling clients. Because such context-agnostic objects "jump" from one context to the next, they are referred to as context-agile objects. The clients of a context-agile object each have a direct reference to it, and no proxies are involved when making intra-app domain calls. Note that objects that derive from MarshalByRefObject are accessed via a proxy across app domains but are agile inside an app domain. Marshal-by-value objects are also context-agile.

The other type of object is called a context-bound object. Context-bound objects always execute in the same context. The designation and affinity of a context-bound object to a context is decided when the object is created and is fixed for the life of the object. To qualify as a context-bound object, the object must derive directly (or have one of its base classes derive) from the abstract class ContextBoundObject:

     public class MyClass : ContextBoundObject     {...} 

The client of a context-bound object never has a direct reference to it. Instead, the client always interacts with a context-bound object via a proxy. Because ContextBoundObject is derived from MarshalByRefObject, every context-bound object is also marshaled by reference across app domain boundaries. This makes perfect sense, because the context-bound object can't leave its context, let alone its app domain.

11.1.2. Component Services Types

.NET provides two kinds of component services: context-bound services and Enterprise Services. The context-bound services are available to any context-bound object. .NET offers only one such service: the synchronization domain, described in Chapter 8. Using the Synchronization context attribute, a context-bound component gains automatic synchronization and lock sharing:

     [Synchronization]     public class MyClass : ContextBoundObject     {        public MyClass( )        {}        public void DoSomething( )        {}     } 

When you add the Synchronization attribute, .NET ensures that only one thread at a time is allowed to access the object, without requiring you to spend the effort implementing this functionality yourself, and you don't have to worry about deadlocks. Clients of such objects don't need to worry about synchronization either. Although this is the only context-bound service provided out-of-the-box, the .NET context is an extensible mechanism, and you can define your own custom context attributes for custom services and extensions. The rest of this chapter examines the .NET context and context-bound objects in detail, and demonstrates how to develop custom context-bound services and attributes.

The second kind of component services are .NET Enterprise Services (see the sidebar ".NET Enterprise Services"). Enterprise Services offer more than 20 component services covering an impressive array of domains, from transactions to loosely coupled events to web services. Enterprise Services are available only to classes derived from the class ServicedComponent. ServicedComponent is in turn derived from ContextBoundObject, so you can say that Enterprise Services are a specialization of context-bound services. If you develop a serviced component, you normally indicate which services the component relies on by using dedicated attributes.

Enterprise Services attributes aren't .NET context attributes, but rather COM+ context attributes.


.NET Enterprise Services

.NET Enterprise Services are a set of component services designed to ease the development of Enterprise applications. .NET Enterprise Services are the result of integrating COM+ into .NET, and they offer the same range of services essential to any Enterprise application. For the most part, the semantics of the services, the algorithms behind them, the benefits, and the implied programming models remain exactly the same as they were for COM components. .NET components that take advantage of Enterprise Services are called serviced components because they derive from the class ServicedComponent, defined in the System.EnterpriseServices namespace. You can configure the services by using context attributes in your code. For example, if you want .NET to maintain a pool of your objects, and you want there to be at least 3 but no more than 10 objects in the pool, use the ObjectPooling attribute:

     using System.EnterpriseServices;           [ObjectPooling(MinPoolSize = 3,MaxPoolSize = 10)]     public class MyComponent : ServicedComponent     {...} 

If you also want transaction support, use the transaction attribute:

     using System.EnterpriseServices;           [Transaction]     [ObjectPooling(MinPoolSize = 3,MaxPoolSize = 10)]     public class MyComponent : ServicedComponent     {...} 

You can also configure the pool parameters (and any other services) after deployment by using the COM+ Component Services Explorer. However, due to .NET's ability to persist the attributes in the assembly metadata, there is often no need to use the Component Services Explorer for services configuration. You can read about .NET Enterprise Services in my book COM and .NET Component Services (O'Reilly).




Programming. NET Components
Programming .NET Components, 2nd Edition
ISBN: 0596102070
EAN: 2147483647
Year: 2003
Pages: 145
Authors: Juval Lowy

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net