0

I wish to do the below using the fluent api
Modify the configuration at run time; perhaps to take into account external factors or changes to the environment.
https://msdn.microsoft.com/en-us/library/ff664363(PandP.50).aspx
But I get into issues. The problem is exactly same as the below link. Change Enterprise Library configuration midway in a program

Community
  • 1
  • 1
Lalit Singh Rana
  • 137
  • 1
  • 1
  • 10

1 Answers1

1

This code works in Enterprise Library 6:

class Program
{
    static void Main(string[] args)
    {
        FirstConfig();
        Logger.Write("Before processing", "General"); //Some wrapper around EntLib logger methods

        //Do some processing for some time

        SecondConfig();
        Logger.Write("After after processing", "General");
    }

    private static void FirstConfig()
    {
        var textFormatter = new FormatterBuilder()
            .TextFormatterNamed("First Text Formatter")
            .UsingTemplate("{message}");

        var builder = new ConfigurationSourceBuilder();
        builder.ConfigureLogging()
            .WithOptions.DoNotRevertImpersonation()
            .LogToCategoryNamed("General").WithOptions.SetAsDefaultCategory()
            .SendTo.FlatFile("First Listener")
            .FormatWith(textFormatter).WithHeader("").WithFooter("")
            .ToFile("BeforeChange.log");

        var configSource = new DictionaryConfigurationSource();
        builder.UpdateConfigurationWithReplace(configSource);

        Logger.SetLogWriter(new LogWriterFactory(configSource).Create());
    }

    private static void SecondConfig()
    {
        var textFormatter = new FormatterBuilder()
            .TextFormatterNamed("Second Text Formatter")
            .UsingTemplate("{message}");

        var builder = new ConfigurationSourceBuilder();
        builder.ConfigureLogging()
            .WithOptions.DoNotRevertImpersonation()
            .LogToCategoryNamed("General").WithOptions.SetAsDefaultCategory()
            .SendTo.FlatFile("Second Listener")
            .FormatWith(textFormatter).WithHeader("").WithFooter("")
            .ToFile("AfterChange.log");

        var configSource = new DictionaryConfigurationSource();
        builder.UpdateConfigurationWithReplace(configSource);

        // Dispose any existing loggers
        Logger.Reset();
        Logger.SetLogWriter(new LogWriterFactory(configSource).Create());
    }
}

After running this there will be two log files created: BeforeChange.log and AfterChange.log

For EntLib 5 the code is very similar except that the container needs to be setup:

class Program
{
    static void Main(string[] args)
    {
        FirstConfig();
        Logger.Write("Before processing", "General"); //Some wrapper around EntLib logger methods

        //Do some processing for some time

        SecondConfig();
        Logger.Write("After after processing", "General");
    }

    private static void FirstConfig()
    {
        var textFormatter = new FormatterBuilder()
            .TextFormatterNamed("First Text Formatter")
            .UsingTemplate("{message}");

        var builder = new ConfigurationSourceBuilder();
        builder.ConfigureLogging()
            .WithOptions.DoNotRevertImpersonation()
            .LogToCategoryNamed("General").WithOptions.SetAsDefaultCategory()
            .SendTo.FlatFile("First Listener")
            .FormatWith(textFormatter).WithHeader("").WithFooter("")
            .ToFile("BeforeChange.log");

        var configSource = new DictionaryConfigurationSource();
        builder.UpdateConfigurationWithReplace(configSource);

        EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(configSource);
    }

    private static void SecondConfig()
    {
        var textFormatter = new FormatterBuilder()
            .TextFormatterNamed("Second Text Formatter")
            .UsingTemplate("{message}");

        var builder = new ConfigurationSourceBuilder();
        builder.ConfigureLogging()
            .WithOptions.DoNotRevertImpersonation()
            .LogToCategoryNamed("General").WithOptions.SetAsDefaultCategory()
            .SendTo.FlatFile("Second Listener")
            .FormatWith(textFormatter).WithHeader("").WithFooter("")
            .ToFile("AfterChange.log");

        var configSource = new DictionaryConfigurationSource();
        builder.UpdateConfigurationWithReplace(configSource);

        // Dispose any existing loggers
        Logger.Reset();
        EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(configSource);
    }
}

The downside of the above EntLib 5 approach is that the second configuration will configure logging but will also wipe out any other blocks that were already configured. The solution is to use Unity directly and keep the same container and just make modifications to the blocks we want changed. In this example FirstConfig() configures data access and logging but SecondConfig only (re)configures logging.

class Program
{
    private static IUnityContainer container = new UnityContainer();

    static void Main(string[] args)
    {
        FirstConfig();
        Logger.Write("Before processing", "General"); //Some wrapper around EntLib logger methods

        EnterpriseLibraryContainer.Current.GetInstance<Database>("MyDatabase");
        //Do some processing for some time

        SecondConfig();

        // This would fail if we cleared the existing configuration because SecondConfig()
        // does not configure the data access block
        EnterpriseLibraryContainer.Current.GetInstance<Database>("MyDatabase");

        Logger.Write("After after processing", "General");
    }

    private static void FirstConfig()
    {
        var textFormatter = new FormatterBuilder()
            .TextFormatterNamed("First Text Formatter")
            .UsingTemplate("{message}");

        var builder = new ConfigurationSourceBuilder();
        builder.ConfigureLogging()
            .WithOptions.DoNotRevertImpersonation()
            .LogToCategoryNamed("General").WithOptions.SetAsDefaultCategory()
            .SendTo.FlatFile("First Listener")
            .FormatWith(textFormatter).WithHeader("").WithFooter("")
            .ToFile("BeforeChange.log");

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

        var configSource = new DictionaryConfigurationSource();
        builder.UpdateConfigurationWithReplace(configSource);

        container.AddNewExtension<EnterpriseLibraryCoreExtension>();

        // Create a configurator to use to configure our fluent configuration
        var configurator = new UnityContainerConfigurator(container);
        EnterpriseLibraryContainer.ConfigureContainer(configurator, configSource);

        // Use the configured container with fluent config as the Enterprise Library service locator
        EnterpriseLibraryContainer.Current = new UnityServiceLocator(container);
    }

    private static void SecondConfig()
    {
        var textFormatter = new FormatterBuilder()
            .TextFormatterNamed("Second Text Formatter")
            .UsingTemplate("{message}");

        var builder = new ConfigurationSourceBuilder();
        builder.ConfigureLogging()
            .WithOptions.DoNotRevertImpersonation()
            .LogToCategoryNamed("General").WithOptions.SetAsDefaultCategory()
            .SendTo.FlatFile("Second Listener")
            .FormatWith(textFormatter).WithHeader("").WithFooter("")
            .ToFile("AfterChange.log");

        var configSource = new DictionaryConfigurationSource();
        builder.UpdateConfigurationWithReplace(configSource);

        // Dispose any existing loggers
        Logger.Reset();

        var configurator = new UnityContainerConfigurator(container);
        EnterpriseLibraryContainer.ConfigureContainer(configurator, configSource);
    }
}
Randy Levy
  • 22,566
  • 4
  • 68
  • 94