How to make Singleton in an MVC 5 session specific?

I have a Singleton model model in my MVC application to determine if a user is logged in with / admin authorization (based on membership in certain AD groups). This model class must be Singleton, so user permissions can be set once at the first login and used throughout the session:

public sealed class ApplicationUser
{
    // SINGLETON IMPLEMENTATION
    // from http://csharpindepth.com/articles/general/singleton.aspx#lazy
    public static ApplicationUser CurrentUser { get { return lazy.Value; } }

    private static readonly Lazy<ApplicationUser> lazy = 
        new Lazy<ApplicationUser>(() => new ApplicationUser());

    private ApplicationUser()
    {
        GetUserDetails(); // determine if user is authorized/admin 
    }

    // Public members
    public string Name { get { return name; } }
    public bool IsAuthorized { get { return isAuthorized; } }
    public bool IsAdmin { get { return isAdmin; } }

    // Private members
    // more code
}

Singleton is first created in my EntryPointController, from which all other controllers get:

public abstract class EntryPointController : Controller
{
    // this is where the ApplicationUser class in instantiated for the first time
    protected ApplicationUser currentUser = ApplicationUser.CurrentUser;        
    // more code
    // all other controllers derive from this
}

These patterns allow me to use ApplicationUser.CurrentUser.Nameor ApplicationUser.CurrentUser.IsAuthorizedetc. throughout my application.

:
, -! , , !

Singleton?

+4
3

Singleton-Multiton ( @Kickaha Multiton).

public sealed class ApplicationUser
{
    // SINGLETON-LIKE REFERENCE TO CURRENT USER ONLY

    public static ApplicationUser CurrentUser
    { 
        get 
        { 
            return GetUser(HttpContext.Current.User.Identity.Name); 
        } 
    }

    // MULTITON IMPLEMENTATION (based on http://stackoverflow.com/a/32238734/979621)

    private static Dictionary<string, ApplicationUser> applicationUsers 
                            = new Dictionary<string, ApplicationUser>();

    private static ApplicationUser GetUser(string username)
    {
        ApplicationUser user = null;

        //lock collection to prevent changes during operation
        lock (applicationUsers)
        {
            // find existing value, or create a new one and add
            if (!applicationUsers.TryGetValue(username, out user)) 
            {
                user = new ApplicationUser();
                applicationUsers.Add(username, user);
            }
        }

        return user;
    }

    private ApplicationUser()
    {
        GetUserDetails(); // determine current user AD groups and access level
    }

    // REST OF THE CLASS CODE

    public string Name { get { return name; } }
    public bool IsAuthorized { get { return isAuthorized; } }
    public bool IsAdmin { get { return isAdmin; } }

    private string name = HttpContext.Current.User.Identity.Name;
    private bool isAuthorized = false;
    private bool isAdmin = false;

    // Get User details
    private void GetUserDetails()
    {
        // Check user AD groups and determine isAuthorized and isAdmin
    }
}

.

EntryPointController:

public abstract class EntryPointController : Controller
{
    // this is where the ApplicationUser class in instantiated for the first time
    protected ApplicationUser currentUser = ApplicationUser.CurrentUser;        
    // more code
    // all other controllers derive from this
}

ApplicationUser.CurrentUser.Name ApplicationUser.CurrentUser.IsAuthorized ..

+3

, Multiton, .

http://designpatternsindotnet.blogspot.ie/2012/07/multiton.html

using System.Collections.Generic;
using System.Linq;

namespace DesignPatterns
{
    public class Multiton
    {
        //read-only dictionary to track multitons
        private static IDictionary<int, Multiton> _Tracker = new Dictionary<int, Multiton> { };

        private Multiton()
        {
        }

        public static Multiton GetInstance(int key)
        {
            //value to return
            Multiton item = null;

            //lock collection to prevent changes during operation
            lock (_Tracker)
            { 
                //if value not found, create and add
                if(!_Tracker.TryGetValue(key, out item))
                {
                    item = new Multiton();

                    //calculate next key
                    int newIdent = _Tracker.Keys.Max() + 1;

                    //add item
                    _Tracker.Add(newIdent, item);
                }
            }
            return item;
        }
    }
}
+4

Singleton?

.

, -! , . !

, ApplicationUser .

:

I hope this solution makes sense to you. :)

+1
source

All Articles