Static Singleton In ASP.Net Session
我一直在读ASP.NET中关于单例的内容,我看到了各种实现和建议。我尝试在这之后对我的实现进行建模:https://stackoverflow.com/…asp-net-singleton
这是我的问题:我想要一个我正在实例化的对象,以维持当前会话的生命,但不能在会话之间共享。例如,如果两个用户同时登录,我希望他们各自"拥有"一个全局对象的实例。下面是我的实现。这是正确的方法吗?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | public class AppGlobal { #region Contructors public AppGlobal() { } public static AppGlobal Instance { get { HttpSessionState session = HttpContext.Current.Session; if (session["AppGlobalInstance"] == null) { session["AppGlobalInstance"] = new AppGlobal(); } return (AppGlobal)session["AppGlobalInstance"]; } } #endregion #region Public Properties public User UserObject { get; set; } public Campaign CampaignObject { get; set; } public List<int> SelectedContactIDs = new List<int>(); public List<int> UnsubmittedContactIDs = new List<int>(); public List<int> SubmittedContactIDs = new List<int>(); public List<int> ProcessedContactIDs = new List<int>(); #endregion #region Public Instance Methods public void ClearCampaign() { CampaignObject = null; UnsubmittedContactIDs.Clear(); SubmittedContactIDs.Clear(); ProcessedContactIDs.Clear(); SelectedContactIDs.Clear(); } public void LoadCampaign(int campaignID) { //Ensure that old data is overwritten MailCampaignManagerEntities db = new MailCampaignManagerEntities(); db.Campaigns.MergeOption = System.Data.Objects.MergeOption.OverwriteChanges; //Clear the campaign and associated data ClearCampaign(); //Set campaign object in AppGlobal this.CampaignObject = db.Campaigns.SingleOrDefaultasp.net(x => x.CampaignID == campaignID); //Populate Contact Status Lists this.UnsubmittedContactIDs.AddRange(from x in this.CampaignObject.CampaignContacts where x.ContactSubmissionID == null select x.CampaignContactID); this.SubmittedContactIDs.AddRange(from x in this.CampaignObject.CampaignContacts where x.ContactSubmissionID != null select x.CampaignContactID); this.ProcessedContactIDs.AddRange(from x in this.CampaignObject.CampaignContacts where x.ContactSubmissionID != null && x.ContactSubmission.DateProcessed != null select x.CampaignContactID); } #endregion #region Public Static Methods public static void WriteLogEntry(int? campaignID, int? contactSubmissionID, int? scheduledDropID, int? userID, string activityDescription) { ActivityLog activityLog = new ActivityLog(); activityLog.CampaignID = campaignID; activityLog.ContactSubmissionID = contactSubmissionID; activityLog.ScheduledDropID = scheduledDropID; activityLog.UserID = userID; activityLog.Text = activityDescription; activityLog.CreatedDate = DateTime.Now; using (MailCampaignManagerEntities db = new MailCampaignManagerEntities()) { db.ActivityLogs.AddObject(activityLog); db.SaveChanges(); } } #endregion } |
实现通常应该是"好的",但是…
您应该根据配置的sessionstatemodule将对象标记为
您可能需要检查当前是否有任何会话,或者您可以获得一个
由于在检查和设置会话变量的过程中存在竞争条件,应用程序可能会为单个会话分配两次AppGlobal对象。我不认为这是一个问题,但如果你想包括更多的花哨的东西,这是需要记住的。为了防止出现这种情况,您可以这样使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public class AppGlobal { private static object _syncRoot = new object(); public static AppGlobal Instance { get { HttpSessionState session = HttpContext.Current.Session; lock (_syncRoot) { if (session["AppGlobalInstance"] == null) { session["AppGlobalInstance"] = new AppGlobal(); } } return (AppGlobal)session["AppGlobalInstance"]; } } } |
如果要在对象中存储禁止序列化的内容,并且需要支持其他sessionstatemodules,可以将实例存储在使用经典单例模式的集合中(这里是一个很好的实现)。同时行动可能是个不错的选择。作为密钥,您可以使用一些您在会话中存储的独特的东西,比如guid。当会话以任何方式结束时,需要从集合中删除该条目。
会话对象本质上来自于单例对象的字典。因此,当您引用会话对象时,您已经从场景后面的单例模式中获益。因此,不需要通过将会话对象放入单例模式来重新发明控制盘。
这看起来像一个有效的单例模式。在会话中,它看起来也是一个非常大的对象。如果有很多用户,可能会遇到性能和内存问题。