首页 > 解决方案 > 带参数的辅助对象的单个实例

问题描述

我们的一个项目使用键值对,其中某些运行时参数(不会在每个程序实例中改变)决定了获得的值。例如:

程序test以参数模式"Municipal"运行:

Key: "testMunicipalDirectory"
Value: "C:\Foo\Bar\"

程序使用参数运行"State"

Key: "StateDirectory"
Value: "C:\Bar\Baz\"

为了让它稍微复杂一点,如果没有匹配的键,比如说"testMunicipalImagesDirectory",有一个后备"defaultImagesDirectory"

Key: "testMunicipalImagesDirectory" ?? "defaultImagesDirectory"
Value: "C:\Foo\Bar\Images" ?? "C:\Images"

目前,有很多代码重复/效率低下,并且存在错误空间。每次引用其中一个时,都会发生字符串连接和空合并以及其他事情。

看起来这将受益于在初始化时传递某些参数(test或不,"State""Municipal"等)的单实例对象,这将为键表示的每个不同属性返回正确的值。

我发现许多关于如何使用带参数的单例设计模式的问题的答案基本上可以归结为“如果它使用参数,您可能不想要单例”。在我的情况下,尝试用不同的值初始化对象是无效的,如果发生这种情况应该抛出异常。

这就是我实现这个目标的方式(伪 C#)(延迟加载不是必需的,但在这里使用):

public sealed class Helper
{
    // how can we enforce that Init has been called?
    private static readonly Lazy<Helper> lazyLoader = new Lazy<Helper>(() => new Helper(name, test));

    public static Helper Instance { get { return lazyLoader.Value; } }

    public static void Init(string name, bool test)
    {
        // if it has already been initalized
        throw new InvalidOperationException("This has already been initalized.");
        // else initalize it
    }

    private string Name { get; set; }
    private bool   Test { get; set; }

    private Helper(string name, bool test) { } // assign to properties, any other ctor logic

    public string Directory
        { get { return ValueGetter.Get((this.Test ? "test" : "") + this.Name + "Directory"); } }
}

public static class ValueGetter
{
    public static string Get(string key, string fallbackKey)
    {
        if (Keys.Any(k => k == key))
            return Keys[key].Value;
        else
            return Keys[fallbackKey].Value;
    }
}

但正如你所看到的,还有一些问题。它如何Init在使用之前强制调用,但不要求每次访问时都Instance传递这些参数?Instance

这是正确的方向,还是有更好的设计模式可以使用?

标签: c#design-patternssingleton

解决方案


推荐阅读