简体   繁体   中英

Design pattern for accessing static data

I have a scenario where I have a set of credentials for each environment eg for dev env username1/pwd1, for qa env username2/pwd2, for staging username3/pwd3 and so on. Now I want to create a class which will return me a set of credentials based on the env I feed to it. All the data has to go within code (as per my brilliant boss, no xml files and all), what design pattern I could use so that the code will be elegant and data can be made extensible in future?

Personally, I am used to create a channel attribute:

[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
}

This attribute is set on the Assembly:

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

As the comment said, the value of the attribute is set on compile time by my MSBuild script (too tied to my project to show you this part).

Once you have setup all of this, you can create a simple singleton like this:

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

Then you can access your credentials like this:

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

If you use .Net core, you could use the configuration techniques. They are very powerful and work in asp .net as well as console programs They are very configurable and composable (pass in config via cmd and json for example)

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

What you're after is the Multiton design pattern.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM