【问题标题】:Design pattern for accessing static data访问静态数据的设计模式
【发布时间】:2017-06-26 09:14:28
【问题描述】:

我有一个场景,每个环境都有一组凭据 例如对于 dev env username1/pwd1,对于 qa env username2/pwd2,对于 staging username3/pwd3 等等。 现在我想创建一个类,它将根据我提供给它的环境返回一组凭据。 所有的数据都必须放在代码中(根据我聪明的老板的说法,没有 xml 文件等等),我可以使用什么设计模式来使代码优雅并且将来可以使数据可扩展?

【问题讨论】:

  • 未来可扩展是什么意思?一个简单的单身人士能回答你的问题吗?将来你只需要编辑你的类来扩展数据吗?
  • 您好,我会使用策略设计模式:sourcemaking.com/design_patterns/strategy
  • 定义一个 ICredentialService 并通过 DI 注入它。在 Composition Root,您可以决定需要哪种实现(FakeCredentialService、Design...、Real...、...)
  • 在代码中存储密码不是一个好主意,所以我怀疑这样做的任何代码都可以“优雅”。

标签: c# design-patterns static-data


【解决方案1】:

我个人是习惯创建频道属性的:

[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
public sealed class AssemblyChannelAttribute : Attribute
{
    public ChannelType Type { get; private set; }

    public AssemblyChannelAttribute(ChannelType type)
    {
        this.Type = type;
    }
}

public enum ChannelType
{
    Dev,
    Beta,
    PreProd,
    Prod
}

这个属性是在程序集上设置的:

#if DEBUG
// In release mode, this attribute is set by the MSBuild script
[assembly: AssemblyChannel(ChannelType.Dev)]
#else

正如评论所说,该属性的值是由我的 MSBuild 脚本在编译时设置的(与我的项目太相关,无法向您展示这部分)。

完成所有这些设置后,您可以像这样创建一个简单的单例:

public class Credentials
{
    private static readonly Lazy<Credentials> instanceHolder =
        new Lazy<Credentials>(() => new Credentials());

    public IReadOnlyDictionary<string, string> Passwords { get; private set; }

    public Credentials Instance { get { return instanceHolder.Value; } }

    private Credentials()
    {
        var channel = typeof(Credentials).Assembly
            .GetCustomAttributes<AssemblyChannelAttribute>()
            .ElementAt(0)
            .Type;

        switch (channel)
        {
            case ChannelType.Dev:
                this.Passwords = new ReadOnlyDictionary<string, string>(new Dictionary<string, string>
                {
                    ["User1"] = "Pwd1",
                    ["User2"] = "Pwd2",
                    // etc
                });
                break;
            case ChannelType.Beta:
                // etc
                break;
            case ChannelType.PreProd:
                // etc
                break;
            case ChannelType.Prod:
                // etc
                break;
        }
    }
}

然后您可以像这样访问您的凭据:

var password = Credentials.Instance.Passwords["User1"];

【讨论】:

    【解决方案2】:

    如果您使用 .Net 核心,则可以使用配置技术。 它们非常强大,可以在 asp .net 和控制台程序中使用 它们是非常可配置和可组合的(例如通过 cmd 和 json 传入配置)

    https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration

    【讨论】:

      【解决方案3】:

      您所追求的是Multiton 设计模式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-11-06
        • 1970-01-01
        • 2015-02-27
        • 1970-01-01
        相关资源
        最近更新 更多