【问题标题】:Abstracting away any configuration using IConfigurationStore and IWindsorInstaller使用 IConfigurationStore 和 IWindsorInstaller 抽象出任何配置
【发布时间】:2015-06-30 16:23:09
【问题描述】:

我有多个 IWindsorInstallers 实现。在他们的安装方法中,我希望他们使用一些预定义的值。我希望使用 IConfigurationStore 来执行此操作,但我不清楚如何执行此操作。

我似乎找不到任何代码示例。

我的解决方法是先将这些值注册为容器中的对象,然后在需要这些值的安装程序中解析它们。但我不认为这是一个很好的解决方案。

【问题讨论】:

  • IConfigurationStore 通常由 Windsor 设施之类的东西使用,它们与 Castle.Windsor 紧密耦合 - 通常不是您想要在应用程序中执行的操作。 AppSettings 是提供运行时参数的好方法。我通常这样做:kozmic.net/2014/03/22/…
  • 好的,所以我最好不要尝试使用 IConfigurationStore。有趣的博客文章,但我们无法从静态 XML 文件中检索值。我们试图为组合根创建“全局”的值由控制台参数和其他环境值确定。
  • 使用命令行参数我会简单地做你现在正在做的事情:用解析的值填充一个对象,然后在组合根中注册该对象,以便任何需要它的组件都可以访问它.

标签: c# dependency-injection castle-windsor configurationmanager


【解决方案1】:

您可以抽象出控制台和环境设置。您可以使用@PhilDegenhardt 推荐的文章。一个示例可能如下所示 - 控制台设置来自静态类通过接口,环境设置来自方法。您可以组合/优化和移动类以避免围绕您的应用程序的不良依赖关系以获得所需的行为:

using System;
using System.Collections;
using System.Configuration;
using Castle.Components.DictionaryAdapter;
using Castle.Facilities.TypedFactory;
using Castle.MicroKernel;
using Castle.MicroKernel.Context;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using ConsoleAppStrongTypeConfig;


namespace CastleDictionaryAdapterExample
{
    class Program
    {
        static void Main()
        {
            GetUserSettings();

            var programComponent = ContainerRegistrar.Container.Resolve<IProgramServiceConfigDependent>();

            programComponent.ConfigDependentAction();
            programComponent = ContainerRegistrar.Container.Resolve<IProgramServiceConfigDependent>();
            programComponent.ConfigDependentAction();

            Console.ReadLine();
        }

        private static void GetUserSettings()
        {
            ContainerRegistrar.SetupContainer();

            Console.WriteLine("Enter setting 1");
            Console.WriteLine();

            string setting1 = Console.ReadLine();

            Console.WriteLine("Enter setting 2");
            Console.WriteLine();

            string setting2 = Console.ReadLine();

            GlobalUserConsoleSettings.consoleSettings = new DictionaryAdapterFactory().GetAdapter<IConsoleSettings>(
                new Hashtable() { 
                { "consoleSetting1", setting1 }, 
                { "consoleSetting2", setting2 } }
                );
        }
    }

    public static class GlobalUserConsoleSettings
    {
        public static IConsoleSettings consoleSettings { get; set; }
    }

    public interface IConsoleSettings
    {
        string consoleSetting1 { get; set; }
        int consoleSetting2 { get; set; }
    }

    public interface IEnvironmentSettings
    {
        string environmentSetting1 { get; set; }
        int environmentSetting2 { get; set; }

        long environmentSettingWhichChanges { get; set; }
    }

    public interface IProgramServiceConfigDependent
    {
        void ConfigDependentAction();
    }
    class ProgramServiceConfigDependent : IProgramServiceConfigDependent
    {
        private readonly IConsoleSettings _consoleSettings;
        private readonly IEnvironmentSettings _envSettings;

        public ProgramServiceConfigDependent(IConsoleSettings consoleSettings, IEnvironmentSettings envSettings)
        {
            _consoleSettings = consoleSettings;
            _envSettings = envSettings;
        }

        public void ConfigDependentAction()
        {
            Console.WriteLine("Doing stuff.");
            Console.WriteLine("Console setting 1 :" + _consoleSettings.consoleSetting1);
            Console.WriteLine("Console setting 2 :" + _consoleSettings.consoleSetting2);
            Console.WriteLine("Environment setting 2 :" + _envSettings.environmentSetting1);
            Console.WriteLine("Environment setting 2 :" + _envSettings.environmentSetting2);
            Console.WriteLine("Environment setting which changes with time :" + _envSettings.environmentSettingWhichChanges);
        }
    }

    public static class ContainerRegistrar
    {
        internal static WindsorContainer Container { get; set; }

        public static void SetupContainer()
        {
            var container = new WindsorContainer();
            container.AddFacility<TypedFactoryFacility>();

            container.Register(
               Component.For<IConsoleSettings>().UsingFactoryMethod(GetGlobalUserConsoleSettings),
                Component.For<IEnvironmentSettings>().UsingFactoryMethod(GetLiveEnvironmentSettings).LifestyleTransient(),
                Component.For<IProgramServiceConfigDependent>().ImplementedBy<ProgramServiceConfigDependent>().LifestyleTransient()
                );

            Container = container;
        }

        private static IConsoleSettings GetGlobalUserConsoleSettings(IKernel k, CreationContext c)
        {
            return GlobalUserConsoleSettings.consoleSettings;
        }

        private static IEnvironmentSettings GetLiveEnvironmentSettings(IKernel k, CreationContext c)
        {
            string envSet1 = Environment.CurrentDirectory;
            int envSet2 = Environment.OSVersion.Version.Major;

            long envSet3 = DateTime.UtcNow.Ticks;
            IEnvironmentSettings envSet = new DictionaryAdapterFactory().GetAdapter<IEnvironmentSettings>(
                new Hashtable() { 
                { "environmentSetting1", envSet1 }, 
                { "environmentSetting2", envSet2 },
                { "environmentSettingWhichChanges", envSet3}}
                );

            return envSet;
        }
    }
}

更新

Here 是 Azure/MVC 的示例项目,another one 是控制台应用程序的示例项目。两者都用于强类型配置并抽象出 ConfigurationManager。

【讨论】:

  • 是的,这或多或少是我们所做的,就像 Phil Degenhardt 所说的那样。
  • 奥格尼安。您对我的问题的编辑并不代表我的问题的想法。请允许我按照我的意图提出我自己的问题,而不是按照您的错误理解?
  • 嗨,@Gurdt。我不介意将问题保留原样。因为我的声誉低于 2000,所以我的所有编辑都只是“建议”,并且在应用之前由其他更有信誉的同行进行了修改。从技术上讲 - 我没有直接编辑问题。我很抱歉。
  • 我发现这些问题更适合当前的表述,因为它看起来很像。您使用的机制和您尝试实现的目标通常称为配置抽象。虽然如果你想在方法中推送“动态参数”,有一个很好的解释 docs。如果您的问题是关于“动态参数”一词中使用的传递参数,我将向您粘贴示例代码。
猜你喜欢
  • 2018-06-27
  • 2011-07-23
  • 2021-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-10
  • 2015-09-25
  • 1970-01-01
相关资源
最近更新 更多