简体   繁体   English

这种修改过的C#单例模式是一种很好的做法吗?

[英]Is this modified C# singleton pattern a good practice?

I'm developing a blog application shared by non-profit organizations. 我正在开发一个由非营利组织共享的博客应用程序。 I want each organization to be able to change their own blog settings. 我希望每个组织都能够更改自己的博客设置。 I have taken a singleton pattern (from BlogEngine.net) and modified it. 我采用了单一模式(来自BlogEngine.net)并对其进行了修改。 (I understand that it is no longer a singleton pattern.) I have tested this approach and it seems to work fine in a development environment. (我知道它不再是单例模式。)我已经测试了这种方法,它似乎在开发环境中工作正常。 Is this pattern a good practice? 这种模式是一种很好的做法吗? Are there issues, which may arise when this is placed in a production environment? 是否存在可能在生产环境中出现的问题?

public class UserBlogSettings
    {
    private UserBlogSettings()
    {
        Load();
    }

    public static UserBlogSettings Instance
    {
            get
            {
                string cacheKey = "UserBlogSettings-" + HttpContext.Current.Session["userOrgName"].ToString();
                object cacheItem = HttpRuntime.Cache[cacheKey] as UserBlogSettings;
                if (cacheItem == null)
                {
                    cacheItem = new UserBlogSettings();
                    HttpRuntime.Cache.Insert(cacheKey, cacheItem, null, DateTime.Now.AddMinutes(1),
                                             Cache.NoSlidingExpiration);
                }
                return (UserBlogSettings) cacheItem;
            }
    }
}    

(Portions of code were omitted for brevity.) (为简洁起见,省略了部分代码。)

Thanks for any help, comment, etc. 感谢您的帮助,评论等。

If its per session, store it in the Session and not in the Cache. 如果是每个会话,则将其存储在会话中而不是存储在缓存中。

Also, you're upcasting and downcasting for no reason here: 此外,你在这里无缘无故地向上转播和向下转播:

object cacheItem = HttpRuntime.Cache[cacheKey] as UserBlogSettings;

this removes the unneeded casts 这将删除不需要的演员表

UserBlogSettings cacheItem = HttpRuntime.Cache[cacheKey] as UserBlogSettings;
if (cacheItem == null)
{
    cacheItem = new UserBlogSettings();
    HttpRuntime.Cache.Insert(cacheKey, cacheItem, null, 
                         DateTime.Now.AddMinutes(1),
                         Cache.NoSlidingExpiration);
}
return cacheItem;

You need to use locking to avoid possible race conditions: 您需要使用锁定来避免可能的竞争条件:

    private static Object lock_Instance = new Object ();
    public static UserBlogSettings Instance 
    { 
        get 
        { 
            string cacheKey = "UserBlogSettings-" + HttpContext.Current.Session["userOrgName"].ToString(); 
            UserBlogSettings cacheItem = HttpRuntime.Cache[cacheKey] as UserBlogSettings;
            if (cacheItem == null) 
            {
                lock (lock_Instance)
                {
                    // need to check again in case another thread got in here too
                    cacheItem = HttpRuntime.Cache[cacheKey] as UserBlogSettings;
                    if (cacheItem == null)
                    {
                        cacheItem = new UserBlogSettings();
                        HttpRuntime.Cache.Insert(cacheKey, cacheItem, null, 
                            DateTime.Now.AddMinutes(1), Cache.NoSlidingExpiration);
                    }
                }
            } 
            return cacheItem; 
        } 
    } 

I think your is good in general, but I would suggest a performance enhancement if it becomes necessary (I know... don't optimize until you really need to). 我认为你的一般都很好,但如果有必要,我会建议性能提升(我知道......在你真的需要之前不要进行优化)。

I would probably implement this with a method like this to get the settings object: 我可能会用这样的方法实现这个来获取设置对象:

public static UserBlogSettings getSettings(string orgName, Cache cache) {
  // do the same stuff here, except using the method parameters
}

The reason for this is that HttpContext.Current and HttpRuntime.Cache have to go through some gyrations to get handles to the current Session and Cache. 原因是HttpContext.Current和HttpRuntime.Cache必须通过一些旋转来获取当前Session和Cache的句柄。 If you are calling this from an asp.net page, you already have that stuff in hand. 如果你是从asp.net页面调用它,那么你已经掌握了这些东西。 So use the ones you already have rather than looking them up again. 所以使用你已经拥有的那些而不是再次查找它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM