Multithreaded managed components can use .NET-provided synchronization locks. These are classic locks, such as mutexes and events. However, these solutions all suffer from the deficiencies described at the beginning of Chapter 5. .NET serviced components should use COM+ activity-based synchronization by adding the
Synchronization attribute to the class definition. The
Synchronization attribute's constructor accepts an enum parameter of type
SynchronizationOption, defined as:
public enum SynchronizationOption
For example, use the
SynchronizationOption.Required value to configure your serviced component to require activity-based synchronization:
public class MyComponent :ServicedComponent
The five enum values of
SynchronizationOption map to the five COM+ synchronization support options discussed in Chapter 5.
Synchronization attribute has an overloaded default constructor, which sets synchronization support to
SynchronizationOption.Required. As a result, the following two statements are equivalent:
System.Runtime.Remoting.Contextnamespace contains a context attribute called
Synchronizationthat can be applied to context-bound .NET classes. This attribute accepts synchronization flags similar to
SynchronizationOption, and initially looks like another version of the
Synchronizationclass attribute. However, the
Synchronizationattribute in the
Contextnamespace provides synchronization based on physical threads, unlike the
Synchronizationattribute in the
EnterpriseServicesnamespace, which uses causalities. As explained in Chapter 5, causality and activities are a more elegant and fine-tuned synchronization strategy.
You can access the COM+ Catalog from within any .NET managed component (not only serviced components). To write installation or configuration code (or manage COM+ events), you need to add to your project a reference to the COM+ Admin type library. After you add the reference, the Catalog interfaces and objects are part of the
COMAdmin namespace. Example 10-10 shows how to create a catalog object and use it to iterate over the application collection, tracing to the Output window the names of all COM+ applications on your computer.
Example 10-10: Accessing the COM+ Catalog and tracing the COM+ application names
int i;//Application index
catalog = (ICOMAdminCatalog)new COMAdminCatalog( );
applicationCollection = (ICatalogCollection)catalog.GetCollection("Applications");
//Read the information from the catalog
applicationCount = applicationCollection.Count;
for(i = 0;i< applicationCount;i++)
//Get the current application
int index = i+1;
String traceMessage = index.ToString()+". "+application.Name.ToString( );
System.EnterpriseServices.Adminnamespace contains the COM+ Catalog object and interface definitions. However, in the Visual Studio.NET Beta 2, the interfaces are defined as private to that assembly. As a result, you cannot access them. The obvious workaround is to import the COM+ Admin type library yourself, as demonstrated in Example 10-10. In the future, you will probably be able to use
System.EnterpriseServices.Adminnamespace directly. The resulting code, when programming directly using the
System.EnterpriseServices.Adminnamespace, is almost identical to Example 10-10.
.NET has an elaborate component-oriented security model. .NET security model manages what the component is allowed to do and what permissions are given to the component and all its clients up the call chain. You can (and should) still manage the security attributes of your hosting COM+ application to authenticate incoming calls, authorize callers, and control impersonation level.
.NET also has what .NET calls role-based security, but that service is limited compared with COM+ role-based security. A role in .NET is actually a Windows NT user group. As a result, .NET role-based security is only as granular as the user groups in the hosting domain. Usually, you do not have control over your end customer's IT department. If you deploy your application in an environment where the user groups are coarse, or where they do not map well to actual roles users play in your application, then .NET role-based security is of little use to you. COM+ roles are unrelated to the user groups, allowing you to assign roles directly from the application business domain.
Configuring Application-Level Security Settings
The assembly attribute
ApplicationAccessControl is used to configure all the settings on the hosting COM+ application's Security tab.
You can use
ApplicationAccessControl to turn application-level authentication on or off:
ApplicationAccessControl attribute has a default constructor, which sets authorization to
true if you do not provide a construction value. Consequently, the following two statements are equivalent:
If you do not use the
ApplicationAccessControl attribute at all, then when you register your assembly, the COM+ default takes effect and application-level authorization is turned off.
ApplicationAccessControl attribute has three public properties you can use to set the access checks, authentication, and impersonation level. The
AccessChecksLevel property accepts an enum parameter of type
AccessChecksLevelOption, defined as:
public enum AccessChecksLevelOption
AccessChecksLevel is used to set the application-level access checks to the process only (
AccessChecksLevelOption.Application) or process and component level (
AccessChecksLevelOption.ApplicationComponent). If you do not specify an access level, then the
ApplicationAccessControl attribute's constructors set the access level to
AccessChecksLevelOption.ApplicationComponent, the same as the COM+ default.
Authentication property accepts an enum parameter of type
AuthenticationOption, defined as:
public enum AuthenticationOption
The values of
AuthenticationOption map to the six authentication options discussed in Chapter 7. If you do not specify an authentication level or if you use the
Default value, the
ApplicationAccessControl attribute's constructors set the authentication level to
AuthenticationOption.Packet, the same as the COM+ default.
Impersonation property accepts an enum parameter of type
ImpersonationLevelOption, defined as:
public enum ImpersonationLevelOption
The values of
ImpersonationLevelOption map to the four impersonation options discussed in Chapter 7. If you do not specify an impersonation level or if you use the
Default value, then the
ApplicationAccessControl attribute's constructors set the impersonation level to
ImpersonationLevelOption.Impersonate, the same as the COM+ default.
Example 10-11 demonstrates using the
ApplicationAccessControl attribute with a server application. The example enables application-level authentication and sets the security level to perform access checks at the process and component level. It sets authentication to authenticate incoming calls at the packet level and sets the impersonation level to
Example 10-11: Configuring a server application security
true,//Authentication is on
A library COM+ application has no use for impersonation level, and it can only choose whether it wants to take part in its hosting process authentication level (that is, it cannot dictate the authentication level). To turn authentication off for a library application, set the authentication property to
AuthenticationOption.None. To turn it on, use any other value, such as
AuthenticationOption.Packet. Example 10-12 demonstrates how to use the
ApplicationAccessControl to configure the security setting of
a library application.
Example 10-12: Configuring a library application security
//use AuthenticationOption.None to turn off authentication,
//and any other value to turn it on