Fluent API仅生效一次(企业库) [英] Fluent API takes effect only once (Enterprise Library)

查看:214
本文介绍了Fluent API仅生效一次(企业库)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望使用流畅的api执行以下操作:

在运行时修改配置;也许是考虑到外部因素或环境的变化。

> https://msdn.microsoft.com/zh-CN/library/ff664363(PandP.50).aspx


但是我遇到了问题。问题与下面的链接完全相同。
在程序中途更改企业库配置

解决方案

此代码在Enterprise Library 6中有效:



< pre class = lang-cs prettyprint-override> class程序
{
static void Main(string [] args)
{
FirstConfig() ;
Logger.Write(处理之前,常规); // EntLib记录器方法周围的一些包装器

//进行一段时间的处理

SecondConfig();
Logger.Write(处理后,常规);
}

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);

//处置所有现有记录器
Logger.Reset();
Logger.SetLogWriter(new LogWriterFactory(configSource).Create());
}
}

运行此命令后,将创建两个日志文件: BeforeChange.log和AfterChange.log



对于EntLib 5,代码非常相似,只是需要设置容器:

  class程序
{
static void Main(string [] args)
{
FirstConfig ();
Logger.Write(处理之前,常规); // EntLib记录器方法周围的一些包装器

//进行一段时间的处理

SecondConfig();
Logger.Write(处理后,常规);
}

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);

//处置所有现有记录器
Logger.Reset();
EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(configSource);
}
}

上述EntLib 5方法的缺点是第二种配置将配置日志记录,但也会清除所有其他已配置的块。解决方案是直接使用Unity并保留相同的容器,然后对我们要更改的块进行修改。在此示例中,FirstConfig()配置数据访问和日志记录,但仅SecondConfig(重新)配置日志记录。

  class程序
{
私有静态IUnityContainer容器= new UnityContainer();

静态void Main(string [] args)
{
FirstConfig();
Logger.Write(处理之前,常规); // EntLib记录器方法周围的一些包装器

EnterpriseLibraryContainer.Current.GetInstance< Database>( MyDatabase);
//进行一段时间的处理

SecondConfig();

//如果我们清除了现有配置,这将失败,因为SecondConfig()
//没有配置数据访问块
EnterpriseLibraryContainer.Current.GetInstance< Database>( MyDatabase);

Logger.Write(处理后,常规);
}

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);

容器。AddNewExtension< EnterpriseLibraryCoreExtension>();

//创建一个配置器以配置我们的流利配置
var configurator = new UnityContainerConfigurator(container);
EnterpriseLibraryContainer.ConfigureContainer(configurator,configSource);

//将配置好的容器与流畅的配置一起用作企业库服务定位器
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);

//处置所有现有记录器
Logger.Reset();

var configurator = new UnityContainerConfigurator(container);
EnterpriseLibraryContainer.ConfigureContainer(configurator,configSource);
}
}


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

解决方案

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);
    }
}

这篇关于Fluent API仅生效一次(企业库)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆