将ASP.net Singleton会话实例转换为对象

时间:2011-10-13 23:00:41

标签: session singleton instance

所以我接手了另一位开发人员的VB.net Web应用程序项目,并发现了迄今为止编写的代码的明显问题。

开发人员已根据本教程(http://net.tutsplus.com/tutorials/other/build-a-shopping-cart-in-aspnet/)构建了购物车应用程序。

注意:对于任何考虑使用此作为生产ASP.net购物车基础的开发人员 - 请勿 - 继续阅读以了解更多信息....

编写该教程的人意识到使用Singleton对于基于会话的购物车来说并不是一个非常聪明的模式。事实上,它是愚蠢的 - 真的很愚蠢。使用此模式,每个用户都拥有相同的购物车实例!

本教程中有很多有用的注释,介绍如何将Singleton实例会话转换为对象(如作者的这一个:http://net.tutsplus.com/tutorials/other/build-a-shopping-cart-in-aspnet/comment-page-1/#comment-56782)。

但我的应用程序使用VB.net等效(在该页面上的下载文件中可用),我想知道的是我需要通过整个应用程序并删除所有类似的引用:

ShoppingCart.Instance.AddItem

并用以下内容手动替换它们:

Dim cart As ShoppingCart = ShoppingCart.GetShoppingCart()

cart.AddItem(3)

或者我能做些什么来转换这段代码:

#Region "Singleton Implementation"

' Readonly variables can only be set in initialization or in a constructor
Public Shared ReadOnly Instance As ShoppingCart
' The static constructor is called as soon as the class is loaded into memory
Shared Sub New()
    ' If the cart is not in the session, create one and put it there
    ' Otherwise, get it from the session
    If HttpContext.Current.Session("ASPNETShoppingCart") Is Nothing Then
        Instance = New ShoppingCart()
        Instance.Items = New List(Of CartItem)
        HttpContext.Current.Session("ASPNETShoppingCart") = Instance
    Else
        Instance = CType(HttpContext.Current.Session("ASPNETShoppingCart"), ShoppingCart)
    End If

进入其他东西,所以我不需要更改实例调用?

e.g。像这样的东西(这是我在文章的另一条评论中找到的C#代码片段 - 我需要一个VB.net等价物,但我不知道怎么写它 - 我的VB.net有点生锈!)< / p>

public static ShoppingCart Instance
{
    get
    {
        ShoppingCart c=null;
        if (HttpContext.Current.Session["ASPNETShoppingCart"] == null)
        {
            c = new ShoppingCart();
            c.Items = new List();
            HttpContext.Current.Session.Add(“ASPNETShoppingCart”, c);
        }
        else
        {
            c = (ShoppingCart)HttpContext.Current.Session["ASPNETShoppingCart"];
        }
        return c;
    }
}

感谢您提供的任何帮助。

2 个答案:

答案 0 :(得分:0)

修改

如果您执行上述代码,则无需更改实例调用。在大多数实例调用中,它们创建静态对象(如果为null)并将其填充到静态成员变量中并继续将其移出(可能还有一些双锁检查)。在上面的代码中,你没有这样做 - 你转过来并在会话状态字典中给出一个,这样每个字典都会得到一个不同的字典。

在这种情况下,术语实例会有点误导,但您不必更改所有调用代码。它在逻辑上是他们购物车的一个实例。

...

使用HttpContext.Current.Session字典将允许您将购物车存储在每个购物用户的内存中。

内存中会话的缺点是,如果IIS应用程序池回收,它将会消失。此外,如果您必须添加另一个Web服务器(向外扩展),您将需要使用NLB亲和力 - 它只是限制您的选项。你的记忆力也会增长,因为他们的购物车会在整个会话期间保留在内存中 - 但这对购物网站来说是一个很好的问题:)但是,它简单而且重量轻。

其他选项是通过配置在数据库中存储会话状态或滚动您自己的购物车表。

另一种选择是使用云存储 - 类似于Azure表服务。这样你就可以获得两全其美的效果 - 你不需要维护你的SQL服务器,你可以获得冗余和耐用性等等......而且 - 嘿 - 你可以同时使用新技术:)

答案 1 :(得分:0)

使用此代码

public static ShoppingCart Instance     {         得到         {

        if (HttpContext.Current.Session["ASPNETShoppingCart"] == null)
        {

            // we are creating a local variable and thus

            // not interfering with other users sessions

            ShoppingCart instance = new ShoppingCart();

            instance.Items = new List<CartItem>();

            HttpContext.Current.Session["ASPNETShoppingCart"] = instance;

            return instance;

        }
        else
        {

            // we are returning the shopping cart for the given user

            return (ShoppingCart)HttpContext.Current.Session["ASPNETShoppingCart"];

        }

    }
}