开发者

Object that is needed throughout the application

I have an application that gets some data from the user when the application loads and is needed throughout the application, what is the best way to keep hold of the object that holds this data throughout the entire lifetime of the ap开发者_运维知识库plication?

This data needs to be available to most other objects created during the lifetime of the application.

I learnt the other day that Singletons are not necessarily a good idea. Especially in multi threaded environments, which my application is.

I have been using Singletons to handle this problem, but I wondered if this is a good way to deal with this?

EDIT:

Let me elobarate: I'm asking for username and password when the application starts, now I know keeping a password in-memory is out security and bad practice, but throughout the logon process there is quite a few places I need this data to check various things, so this is where I used a Singleton.


I'd advise against using a class that defines its own singleton just because that usually means you'll have pains during unit testing.

If you use a generic singleton, you'll have the same functionality, but with added benefits later on when testing / moving away from the singleton pattern (going multi-users for example).

Note that the singleton is initialized with a delegate. The rationale here is that the delegate will only be called once, even if two threads are somehow registering the singleton at the same time...

Using an interface makes your life easier when writing unit tests as you can mock the part of the singleton you are interested in for your test (or your ultra quick - 2 minutes before demoing to the CEO patch/debugging session).

It might be overkill for storing a login/pass tuple, but this pattern saved my bacon more times than I care to count.

public static class Singleton<T>
{
    private static T instance;
    private static readonly object sync = new object();
    static bool registered = false;

    public static T Instance
    {
        get
        {
            return instance;
        }
    }

    public static void Register(Func<T> constructor)
    {
        lock (sync)
        {
            if (!registered)
            {
                instance = constructor();
                registered = true;
            }
        }
    }
}

class Demo
{
    class Data
    {
        public string Pass { get; set; }
        public string Login { get; set; }
    }

    void SimpleUsage()
    {
        string login = "SEKRIT";
        string pass = "PASSWORD";

        // setup 
        Singleton<Data>.Register(() => new Data { Login = login, Pass = pass });

        // 
        var ltCommander = Singleton<Data>.Instance;
    }

    /// <summary>
    /// Using an interface will make the singleton mockable for tests! 
    /// That's invaluable when you'll want to fix something FAST without running the whole app!
    /// </summary>
    interface IData
    {
        string Login { get; }
        string Password { get; }
    }

    class UnitTestFriendlyData : IData
    {
        public UnitTestFriendlyData(string login, string password)
        {
            Login = login;
            Password = password;
        }


        public string Login { get; private set; }
        public string Password { get; private set; }
    }

    void SmarterUsage()
    {
        // same setup, but through the interface. 
        Singleton<IData>.Register(() => new UnitTestFriendlyData("login", "pass"));

        // and same for the retrieval
        var data = Singleton<IData>.Instance;

    }


    void UnitTestSetupWithMoq()
    {
        // Register a mock.
        var mock = new Mock<IData>();
        mock.SetupProperty(x => x.Login, "Login");
        mock.SetupProperty(x => x.Pass, "Pass");
        Singleton<IData>.Register(() => mock.Object);

        // and same for the retrieval
        var data = Singleton<IData>.Instance;

    }

}


See this for some explanations

Implementing Singleton in C# , looking at Multithreaded Singleton.

Also Ist way of implementing Singleton Pattern in C#: looking at IIIrd way of implementing Singleton Pattern in C#: Simple Multithreaded Singleton Pattern and IVth way of implementing Singleton Pattern in C#: Multithreaded Singleton Pattern


In this case, a singleton is the proper choice. You just don't want to start shoving in a lot of unrelated stuff in there -- you want the class to remain cohesive and not just a "bag of properties" that sits around. As far as multithreading goes, you can put the appropriate controls on your singleton class, no problem. What types of locks and protections you use, however, is specific to your implementation (there's not enough detail in your question to answer that, though).


My first reaction to this is that if you have a piece of data that is required by most other types in the application, you may want to encapsulate it better. It sounds like a violation of the Single Responsibility Principle. However, without knowing more about your scenario, it difficult to say what the remedy could be.


From the way you described your situation, it sounds like you just want to save off a string once at startup and then it would always just be read-only everywhere else. If this is the case, you can really just do something like:

internal static class LoginInfo
{
    internal static string Username;
    internal static string Password;
}

Then from anywhere in your app you can just say:

var usr = LoginInfo.Username;
var pwd = LoginInfo.Password;

Now i'm sure everyone will comment that is is a terrible design practice, but I'm prepared to live with that :)

Now if you plan on changing the value all the time, and if this wasn't just a string and was instead some more complex object, then thread-safety could certainly become an issue. You could always make a thread-safe getter on a property.


The reason people say that a Singleton isn't necessarily a good idea is because it encourages a scenario like yours. Needing a static object is the bad part - a Singleton is just seen as an enabler.

That said, I can't really comment on whether it's neccesary in your application, because you haven't detailed it. But if you REALLY need static data held in an object for the application's lifetime, go right ahead and use a singleton. You can make them thread-safe as well.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜