views:

263

answers:

4

Hi,

I know this must be an age-old, tired question, but I cant seem to find anything thru my trusty friend (aka Google).

I have a .net 3.5 c# winforms app, that presents a user with a login form on application startup. After a successful login, I want to run off to the DB, pull in some user-specific data and hold them (in properties) in a class called AppCurrentUser.cs, that can thereafer be accessed across all classes in the assembly - the purpose here being that I can fill some properties with a once-off data read, instead of making a call to the DB everytime I need to. In a web app, I would usually use Session variables, and I know that the concept of that does not exist in WinForms.

The class structure resembles the following:

public class AppCurrentUser {

    public AppCurrentUser() { }

    public Guid UserName { get; set; }
    public List<string> Roles { get; set; }
    public string Firstname { get; set; }
    public string Lastname { get; set; }
}

Now, I have some options that I need some expert advice on:

Being a "dumb" class, I should make the properties non-static, instantiate the class and then set the properties...but then I will only be able to access that instance from within the class that it was created in, right?

Logically, I believe that these properties should be static as I will only be using the class once throughout the application (and not creating new instances of it), and it's property values will be "reset" on application close. (If I create an instance of it, I can dispose of it on application close)

How should I structure my class and how do I access its properties across all classes in my assembly? I really would appreciate your honest and valued advice on this!!

Thanks!

+1  A: 

It depends on how you setup your architecture. If you're doing all your business logic code inside the actual form (e.g. coupling it to the UI), then you probably want to pass user information in as a parameter when you make a form, then keep a reference to it from within that form. In other words, you'd be implementing a Singleton pattern.

You could also use Dependency Injection, so that every time you request the user object, the dependency injection framework (like StructureMap) will provide you with the right object. -- you could probably use it like a session variable since you'll be working in a stateful environment.

MunkiPhD
Hi! thanks for the reply! No, my BL is in a separate class and called from the UI. Also, am I valid with my static vs non-static argument?
Shalan
reading up on StructureMap now
Shalan
I would say DI is overkill here. Shalan sounds like he's probably a beginner and dependency injection should be avoided until more basic concepts like Singleton Pattern - as you've suggested - are better grasped.
xanadont
In your first option, do u mean passing in all the information as parameters in each forms' constructor? There's a lot of properties, and that may be undesirable (i.t.o. maintenance) to have property accessors in each form. Another option would be to create an internal static class with these properties that I can theafter use - Your thoughts on that?
Shalan
um...thanks for the assist, but not exactly a noob developer. I admit tho that there r things that I should know like the back of my hand! :)
Shalan
+4  A: 

Use the singleton pattern here:

public class AppUser
{
    private static _current = null;
    public static AppUser Current
    {
        get { return = _current; }
    }

    public static void Init()
    {
        if (_current == null)
        {
            _current = new AppUser();
            // Load everything from the DB.
            // Name = Dd.GetName();
        }
    }

    public string Name { get; private set; }
}

// App startup.
AppUser.Init();

// Now any form / class / whatever can simply do:
var name = AppUser.Current.Name;

Now the "static" things are thread-unsafe. I'll leave it as an exercise of the reader to figure out how to properly use the lock() syntax to make it thread-safe. You should also handle the case if the Current property is accessed before the call to Init.

xanadont
A: 

The correct place to store this type of information is in a custom implementation of IIdentity. Any information that you need to identify a user or his access rights can be stored in that object, which is then associated with the current thread and can be queried from the current thread whenever needed.

This principal is illustrated in Rocky Lhotka's CLSA books, or google winforms custom identity.

Eric J.
A: 

I'm not convinced this is the right way but you could do something like this (seems to be what you're asking for anyway):

public class Sessions
{
    // Variables
    private static string _Username;

    // properties
    public static string Username
    {
        get
        {
            return _Username;
        }
        set
        {
            _Username = value;
        }
    }
}

in case the c# is wrong...i'm a vb.net developer...

then you'd just use Sessions.USername etc etc

davidsleeps
Static properties introduce threading issues and should be addressed.
xanadont