Jaa


Using the Fluent Configuration API

It is possible to programmatically manipulate the default configuration classes used by Enterprise Library for the core, instrumentation, and all of the application blocks. The fluent interface exposed by Enterprise Library is designed to facilitate this process. The fluent interface can be used for all of the configurable features of instrumentation and for all of the Enterprise Library application blocks with the exception of the Validation and Policy Injection Application Blocks.

Using the fluent configuration API, you can:

  • Create configuration sources to pass to Enterprise Library objects that you create in your applications.
  • Create configuration sources for entire sections of the configuration, such as for the Exception Handling Application Block or the Logging Application Block.
  • Create the complete configuration for Enterprise Library for an application.
  • Create different environment-specific configurations for sections or for entire applications; this makes it easier to deploy an application to different run-time environments.
  • Modify the configuration at run time; perhaps to take into account external factors or changes to the environment.

Effectively, the fluent configuration API allows you to specify a set of configuration sections programmatically and, if required, merge them with other configuration settings specified in other sources such as a file configuration source. It also allows you to programmatically define a base configuration that can be changed from another source, such as a file configuration source, which provides the ability to override parts of the base configuration.

Working With the Fluent Configuration API

Enterprise Library provides the ConfigurationSourceBuilder class that acts as the basis for creating configuration sources. Each of the blocks, and the core and instrumentation features of Enterprise Library, provides extensions to this class that expose a fluent interface and make it easy to create configuration sources.

The general approach is to create an instance of the ConfigurationSourceBuilder class and then specify the section you want to configure. The extensions for each configuration section expose intuitive methods that allow you to add the appropriate policies, providers, or other types of extensions to the configuration and specify the required configuration settings for each one. In Visual Studio, the IntelliSense® feature will help you to locate and use the individual methods available for each configuration extension. For example, you can configure instrumentation for a configuration source using the following code.

var builder = new ConfigurationSourceBuilder();

builder.ConfigureInstrumentation()
       .ForApplicationInstance("MyApp")
         .EnableLogging()
         .EnablePerformanceCounters();

var configSource = new DictionaryConfigurationSource();
builder.UpdateConfigurationWithReplace(configSource);
EnterpriseLibraryContainer.Current 
  = EnterpriseLibraryContainer.CreateDefaultContainer(configSource);
'Usage
Dim builder = New ConfigurationSourceBuilder()

builder.ConfigureInstrumentation() _
       .ForApplicationInstance("MyApp") _
         .EnableLogging() _
         .EnablePerformanceCounters() _

Dim configSource = New DictionaryConfigurationSource()
builder.UpdateConfigurationWithReplace(configSource)
EnterpriseLibraryContainer.Current _
  = EnterpriseLibraryContainer.CreateDefaultContainer(configSource)

The final line in this code creates a new container and assigns the configuration to it. Enterprise Library will use this configuration to resolve the objects it requires. You can also use the methods of the IServiceLocator interface to obtain instances of Enterprise Library objects on demand in your code by accessing the IServiceLocator implementation through the EnterpriseLibraryContainer.Current property.

The API also provides methods that allow you to check if a specific section already exists in the configuration, and add new sections to the configuration. For performance reasons, the fluent configuration API does not perform full validity checking of the settings you specify. It does check for null values, however. To obtain full validity checking, you can use the graphical configuration tools to set up and verify your configuration, and then translate it into calls to the configuration API.

All configuration source classes implement the IConfigurationSource interface. This interface allows your application code to subscribe to notifications of configuration changes. For more information, see Updating Configuration Settings at Run Time. By default, in Enterprise Library, only the Logging Application Block registers to receive notifications of configuration changes.

The following examples show how you can configure the other blocks in Enterprise Library using the fluent API:

  • The Caching Application Block
  • The Cryptography Application Block
  • The Data Access Application Block
  • The Exception Handling Block
  • The Logging Application Block
  • The Security Application Block

The Caching Application Block

This example configures a single cache using a cache manager named MyCache that is the default cache for the application. This cache uses an isolated storage backing store named MyStore, and encrypts the content using the symmetric provider named MySymmetric that is defined in the Cryptography Application Block configuration.

var builder = new ConfigurationSourceBuilder();

builder.ConfigureCaching()
       .ForCacheManagerNamed("MyCache")
       .WithOptions
         .UseAsDefaultCache()
         .StoreInIsolatedStorage("MyStore")
         .EncryptUsing.SymmetricEncryptionProviderNamed("MySymmetric");

var configSource = new DictionaryConfigurationSource();
builder.UpdateConfigurationWithReplace(configSource);
EnterpriseLibraryContainer.Current 
  = EnterpriseLibraryContainer.CreateDefaultContainer(configSource);
'Usage
Dim builder = New ConfigurationSourceBuilder()

builder.ConfigureCaching() _
       .ForCacheManagerNamed("MyCache") _
       .WithOptions _
         .UseAsDefaultCache() _
         .StoreInIsolatedStorage("MyStore") _
         .EncryptUsing.SymmetricEncryptionProviderNamed("MySymmetric")

Dim configSource = New DictionaryConfigurationSource()
builder.UpdateConfigurationWithReplace(configSource)
EnterpriseLibraryContainer.Current _
  = EnterpriseLibraryContainer.CreateDefaultContainer(configSource)

The Cryptography Application Block

This example configures a hash provider named MyHashProvider that uses the SHA384 managed algorithm and is the default hash provider, and an encryption provider named MyEncrypt that uses the Rijndael managed algorithm and is the default encryption provider.

var builder = new ConfigurationSourceBuilder();

builder.ConfigureCryptograpy()
       .EncryptUsingHashAlgorithmProviderNamed("MyHashProvider")
         .WithOptions
           .UsingHashAlgorithm<SHA384Managed>()
           .SetAsDefault()
       .EncryptUsingSymmetricAlgorithmProviderNamed("MyEncrypt")
         .WithOptions
           .UsingSymmetricAlgorithm<RijndaelManaged>()
           .UseKeyFile(@"c:\test\mykey.key", DataProtectionScope.LocalMachine)
           .SetAsDefault();

var configSource = new DictionaryConfigurationSource();
builder.UpdateConfigurationWithReplace(configSource);
EnterpriseLibraryContainer.Current 
  = EnterpriseLibraryContainer.CreateDefaultContainer(configSource);
'Usage
Dim builder = New ConfigurationSourceBuilder()

builder.ConfigureCryptograpy() _
       .EncryptUsingHashAlgorithmProviderNamed("MyHashProvider") _
         .WithOptions _
           .UsingHashAlgorithm(Of SHA384Managed)() _
           .SetAsDefault() _
       .EncryptUsingSymmetricAlgorithmProviderNamed("MyEncrypt") _
         .WithOptions _
           .UsingSymmetricAlgorithm(Of RijndaelManaged)() _
           .UseKeyFile("c:\test\mykey.key", DataProtectionScope.LocalMachine) _
           .SetAsDefault()

Dim configSource = New DictionaryConfigurationSource()
builder.UpdateConfigurationWithReplace(configSource)
EnterpriseLibraryContainer.Current _
  = EnterpriseLibraryContainer.CreateDefaultContainer(configSource)

The Data Access Application Block

This example configures a SQL Server database named MyDatabase using a specified connection string as the default database for the application.

var builder = new ConfigurationSourceBuilder();

builder.ConfigureData()
       .ForDatabaseNamed("MyDatabase")
         .ThatIs.ASqlDatabase()
         .WithConnectionString("server=(local); database=Northwind; Integrated Security=true;")
         .AsDefault();

var configSource = new DictionaryConfigurationSource();
builder.UpdateConfigurationWithReplace(configSource);
EnterpriseLibraryContainer.Current 
  = EnterpriseLibraryContainer.CreateDefaultContainer(configSource);
'Usage
Dim builder = New ConfigurationSourceBuilder()

builder.ConfigureData() _
       .ForDatabaseNamed("MyDatabase") _
         .ThatIs.ASqlDatabase() _
         .WithConnectionString("server=(local); database=Northwind; Integrated Security=true;") _
         .AsDefault()

Dim configSource = New DictionaryConfigurationSource()
builder.UpdateConfigurationWithReplace(configSource)
EnterpriseLibraryContainer.Current _
  = EnterpriseLibraryContainer.CreateDefaultContainer(configSource)

The Exception Handling Block

This example configures a single exception handling policy named MyPolicy for exceptions of type NullReferenceException. The handler for this exception policy will log the exception to the General category (defined in the Logging Application Block configuration) as a warning with event ID 9000, wrap the NullReferenceException with an InvalidOperationException, set the new exception message to MyMessage,****and then re-throw the exception.

var builder = new ConfigurationSourceBuilder();

builder.ConfigureExceptionHandling()
       .GivenPolicyWithName("MyPolicy")
       .ForExceptionType<NullReferenceException>()
         .LogToCategory("General")
           .WithSeverity(System.Diagnostics.TraceEventType.Warning)
           .UsingEventId(9000)
         .WrapWith<InvalidOperationException>()
           .UsingMessage("MyMessage")
         .ThenNotifyRethrow();

var configSource = new DictionaryConfigurationSource();
builder.UpdateConfigurationWithReplace(configSource);
EnterpriseLibraryContainer.Current 
  = EnterpriseLibraryContainer.CreateDefaultContainer(configSource);
'Usage
Dim builder = New ConfigurationSourceBuilder()

builder.ConfigureExceptionHandling() _
       .GivenPolicyWithName("MyPolicy") _
       .ForExceptionType(Of NullReferenceException)() _
         .LogToCategory("General") _
           .WithSeverity(System.Diagnostics.TraceEventType.Warning) _
           .UsingEventId(9000) _
         .WrapWith(Of InvalidOperationException)() _
           .UsingMessage("MyMessage") _
         .ThenThrowNewException()

Dim configSource = New DictionaryConfigurationSource()
builder.UpdateConfigurationWithReplace(configSource)
EnterpriseLibraryContainer.Current _
  = EnterpriseLibraryContainer.CreateDefaultContainer(configSource)

The Logging Application Block

This example configures logging without using impersonation for two categories. The first category, named Security, uses a flat file trace listener and a text formatter with a specified template (some of which is omitted here for clarity) to write log events to a file named security.log. The second category, named General and specified as the default category, uses a formatted event log trace listener that, by default, writes log events to the Application log.

var builder = new ConfigurationSourceBuilder();

builder.ConfigureLogging()
       .WithOptions
         .DoNotRevertImpersonation()
       .LogToCategoryNamed("Security")
         .SendTo.FlatFile("Security Log File")
           .FormatWith(new FormatterBuilder()
             .TextFormatterNamed("Text Formatter")
               .UsingTemplate("Timestamp: {timestamp}...{newline})}"))
             .ToFile("security.log")
         .SendTo.EventLog("Formatted EventLog TraceListener")
            .FormatWithSharedFormatter("Text Formatter")
              .ToLog("Application")
       .LogToCategoryNamed("General")
         .WithOptions.SetAsDefaultCategory()
         .SendTo.SharedListenerNamed("Formatted EventLog TraceListener");

var configSource = new DictionaryConfigurationSource();
builder.UpdateConfigurationWithReplace(configSource);
EnterpriseLibraryContainer.Current 
  = EnterpriseLibraryContainer.CreateDefaultContainer(configSource);
'Usage
Dim builder = New ConfigurationSourceBuilder()

builder.ConfigureLogging() _
       .WithOptions _
         .DoNotRevertImpersonation() _
       .LogToCategoryNamed("Security") _
         .SendTo.FlatFile("Security Log File") _
           .FormatWith(New FormatterBuilder() _
             .TextFormatterNamed("Text Formatter") _
               .UsingTemplate("Timestamp: {timestamp}...{newline})}")) _
             .ToFile("security.log") _
         .SendTo.EventLog("Formatted EventLog TraceListener") _
            .FormatWithSharedFormatter("Text Formatter") _
              .ToLog("Application") _
       .LogToCategoryNamed("General") _
         .WithOptions.SetAsDefaultCategory() _
         .SendTo.SharedListenerNamed("Formatted EventLog TraceListener")

Dim configSource = New DictionaryConfigurationSource()
builder.UpdateConfigurationWithReplace(configSource)
EnterpriseLibraryContainer.Current _
  = EnterpriseLibraryContainer.CreateDefaultContainer(configSource)

The Security Application Block

This example configures an authorization rule provider named MyRules containing a single rule, and a default security cache named SecCache that uses the cache named MyCache (defined in the configuration for the Caching Application Block).

var builder = new ConfigurationSourceBuilder();

builder.ConfigureSecurity()
       .AuthorizeUsingRuleProviderNamed("MyRules")
         .SpecifyRule("Rule1", "MyRuleExpression")
       .CacheSecurityInCacheStoreNamed("SecCache")
         .WithOptions
           .UseSharedCacheManager("MyCache")
           .SetAsDefault();

var configSource = new DictionaryConfigurationSource();
builder.UpdateConfigurationWithReplace(configSource);
EnterpriseLibraryContainer.Current 
  = EnterpriseLibraryContainer.CreateDefaultContainer(configSource);
'Usage
Dim builder = New ConfigurationSourceBuilder()

builder.ConfigureSecurity() _
       .AuthorizeUsingRuleProviderNamed("MyRules") _
         .SpecifyRule("Rule1", "MyRuleExpression") _
       .CacheSecurityInCacheStoreNamed("SecCache") _
         .WithOptions _
           .UseSharedCacheManager("MyCache") _
           .SetAsDefault()

Dim configSource = New DictionaryConfigurationSource()
builder.UpdateConfigurationWithReplace(configSource)
EnterpriseLibraryContainer.Current _
  = EnterpriseLibraryContainer.CreateDefaultContainer(configSource)