C# 如何使MVC5中的单例特定于会话?
我的MVC应用程序中有一个单例模型类,用于确定登录的用户是否具有授权/管理权限(基于特定广告组的成员资格)。此模型类需要是单例,以便用户的访问权限可以在首次登录时建立一次,并在整个会话中使用:C# 如何使MVC5中的单例特定于会话?,c#,asp.net-mvc,asp.net-mvc-5,singleton,C#,Asp.net Mvc,Asp.net Mvc 5,Singleton,我的MVC应用程序中有一个单例模型类,用于确定登录的用户是否具有授权/管理权限(基于特定广告组的成员资格)。此模型类需要是单例,以便用户的访问权限可以在首次登录时建立一次,并在整个会话中使用: public sealed class ApplicationUser { // SINGLETON IMPLEMENTATION // from http://csharpindepth.com/articles/general/singleton.aspx#lazy publi
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
}
此模式允许我在整个应用程序中使用ApplicationUser.CurrentUser.Name
或ApplicationUser.CurrentUser.IsAuthorized
等
然而,问题是:Singleton拥有在web应用程序启动时登录的第一个用户的引用!所有后续登录的用户都会看到最早登录的用户的名称强>
如何使单例会话特定?我想您正在寻找多例模式,其中每个实例都链接到一个键 这里有一个例子
使用System.Collections.Generic;
使用System.Linq;
命名空间设计模式
{
公共级多音频
{
//用于跟踪多音的只读字典
私有静态IDictionary _Tracker=新字典{};
私有多通()
{
}
公共静态Multiton GetInstance(int键)
{
//返回值
Multiton项=空;
//锁定集合以防止在操作过程中发生更改
锁定(_跟踪器)
{
//如果未找到值,则创建并添加
如果(!\u Tracker.TryGetValue(输入,输出项))
{
item=新的Multiton();
//计算下一个关键点
int newIdent=_Tracker.Keys.Max()+1;
//添加项
_添加(新标识,项目);
}
}
退货项目;
}
}
}
如何使单例会话特定
将导致您的问题如下
Singleton保存第一个登录用户的引用
在web应用程序启动时!所有后续登录的用户
查看最早登录的用户的名称
我认为您只需要将ApplicationUser
对象存储在每个用户的会话中
机制应如下所示:
应用程序用户
每个经过身份验证的用户创建一个实例ApplicationUser
实例存储在具有密钥的会话中。(不要担心每个用户拥有相同的密钥,因为ASP.NET将为您处理该密钥。)应用程序用户
对象,只需从中获取即可我希望这个解决方案对您有意义。:) 我使用了混合单态多态方法(感谢@Kickaha的多态指针)
在我的模型和其他任何地方,我都可以使用
ApplicationUser.CurrentUser.Name
或ApplicationUser.CurrentUser.IsAuthorized
等访问当前用户的属性。谢谢,您的指针帮助了我!我已经发布了我的工作解决方案。谢谢!我不需要依赖会话
对象就可以完成。请参阅我的工作解决方案。注销后如何从applicationUsers对象中删除用户。否则它将在applicationUsers对象中保持可用。@Oasis:捕捉得好你能解决“绿洲”所指的问题吗?我也在研究类似的解决方案。。。
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
}
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;
}
}
}
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's 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's AD groups and determine isAuthorized and isAdmin
}
}
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
}