2

我试图弄清楚如何通过网络浏览器更改客户的订单。客户将订购带有产品 ID(键)、产品名称、产品价格和他想要的数量的项目。我想知道如何更改他的订单,方法是用旧数量的旧物品替换具有不同数量的相同物品,所以基本上点击选择物品并放置他希望购买的 2 个不同数量的物品。购物车包含购买的物品,所以我想知道如何从购物车中销毁 OrderItem 然后重新创建它。

当我的代码找到已经在购物车中的密钥时,它需要被销毁并使用新的 Quantity(来自网络应用程序的文本框)重新创建。

  protected void btnOrder_Click(object sender, EventArgs e)
{
    //Check for Shoppingcart object
    // Create first if not there
    if (Session["cart"] == null)
        Session["cart"] = new ShoppingCart();
    int quantity = 0;

    // make sure there is text
    if (txtQuantity.Text.Trim().Length != 0)
    {
        quantity = int.Parse(txtQuantity.Text);

        if (((ShoppingCart)Session["cart"]).
            keyExists(int.Parse(productID.Text)))
        {
        //Here I should Destroy the current item that exists and replace with new one

        }
        else  // This is a new item
        {
            // Make the item
            OrderItem item = new OrderItem(
                int.Parse(productID.Text), productName.Text,
                double.Parse(productPrice.Text),
                int.Parse(txtQuantity.Text));
            // add to cart  
            ((ShoppingCart)Session["cart"]).addToCart(item);

        }
        // How does this work? Who is sender?
        this.btnReturn_Click(sender, e);
    }
    else
    {
        Response.Write("Nothing Ordered<br>You must order some of the product or return to the Catalog");
    }

这是 OrderItem 对象

public class OrderItem
{
private int productID;
private string prodName;
private double unitPrice;
private int quantityOrdered;

private string exceptionStr;


public OrderItem(int id, string name, double price, int quantity)
{
    prodName = name;
    exceptionStr = "Numeric data must not be negative";
    if ( id < 0 || price < 0 || quantity < 0)
    {
        throw new System.ArgumentException(exceptionStr);
    }
    else
    {
        productID = id;
        unitPrice = price;
        quantityOrdered = quantity;
    }
}


#region Public Properties
public int ProductID
{
    get
    {
        return productID;
    }
}

public string ProductName
{
    get 
    {
        return prodName;
    }
}


public double UnitPrice
{
    get
    {
        return unitPrice;
    }
}


public int QuantityOrdered
{
    get
    {
        return quantityOrdered;
    }
    set
    {
        if( value < 0 )
        {
            throw new ArgumentException(exceptionStr);
        }
        else
        {
            quantityOrdered = value;
        }
    }
}

#endregion
}

这是购物车供您查看:

 public class ShoppingCart : IEnumerable
 {
private SortedList theCart;

public ShoppingCart() {
    theCart = new SortedList();
} // end of Constructor


public bool HasItems {
    get{
        bool hasItems = false;
        if( theCart.Count > 0 )
            hasItems = true;
        return hasItems;
    }
    set {
        // ignore this is read only
    }
} // end of HasItems


public void addToCart(OrderItem item) {
    theCart.Add(item.ProductID, item);
}// AddToCaArt

/// <summary>
/// deletes item that is passed
/// </summary>
/// <param name="item"></param>
public void deleteFromCart(OrderItem item)
{
    theCart.Remove(item.ProductID);
} // end deleteFromCart

/// <summary>
/// deletes the item with this id key
/// </summary>
/// <param name="id"></param>
public void deleteFromCart(int id)
{
    theCart.Remove(id);
} // end deleteFromCart
public OrderItem[] getCartContents()
{

// need to create stuff
    OrderItem[] stuff = null;
    theCart.Values.CopyTo(stuff, 0);

    return (stuff);
} // end getCartContents


public bool keyExists(int ID) {

    return theCart.ContainsKey(ID);
}// end keyExists

public ICollection Values
{
    get
    {
        return theCart.Values;
    }
}

#region IEnumerable Members

public IEnumerator GetEnumerator()
{
    return theCart.GetEnumerator();
}

#endregion
}
4

4 回答 4

1

I would highly recommend thinking about from a class or model level how a shopping cart would look. I think a set of classes like the following would help a great deal (not the best but an ok design from scratch):

[Serializable]
public class ShoppingCartItem
{
  public ShoppingCartItem(guid key, decimal price, int quantity)
  {
    this.Key = key;
    this.Price = price;
    this.Quantity = quantity;
  }

  public Guid Key { get; private set; }
  public Decimal Price { get; private set; }
  public int Quantity { get; set; }
}

[Serializable]
public class ShoppingCart
{
  public ShoppingCart()
  {
    this.Clear();
  }

  public ICollection<ShoppingCartItem> Items { get; private set; }

  public int ItemCount 
  {
    get { return this.Items.Sum(i => i.Quantity); }
  }

  public decimal Subtotal
  {
    get { return this.Items.Sum(i => i.Quantity * i.Price); }
  }

  public void Clear()
  {
    this.Items = new List<ShoppingCartItem>();
  }
}

Now the ShoppingCart is serializable for the ability to be stored in ASP.Net session (or making a wish list :))

Now I'm not a fan of the loosely typed ASP.Net session so I borrowed, from some where I can't remember, this fantastic class to make strongly typed Session objects:

using System;
using System.Web;

namespace Company.Product.Web.UI.Domain
{
    public abstract class SessionBase<T> where T : class, new()
    {
        private static readonly Object _padlock = new Object();

        private static string Key
        {
            get { return typeof(SessionBase<T>).FullName; }
        }

        public static T Current
        {
            get
            {
                var instance = HttpContext.Current.Session[Key] as T;

                if (instance == null)
                {
                    lock (SessionBase<T>._padlock)
                    {
                        if (instance == null)
                        {
                            HttpContext.Current.Session[Key] = 
                              instance = new T();
                        }
                    }
                }

                return instance;
            }
        }

        public static void Clear()
        {
            var instance = HttpContext.Current.Session[Key] as T;
            if (instance != null)
            {
                lock (SessionBase<T>._padlock)
                {
                    HttpContext.Current.Session[Key] = null;
                }
            }
        }

    }
}

To use it for this example I would then create:

public class ShoppingCartSession : SessionBase<ShoppingCart> { }

Then I can use it anywhere in my code:

var item = ShoppingCartSession.Current.Items.FirstOrDefault(i => i.Key= key);

if (item == null)
{
  ShoppingCartSession.Current.Items.Add(
    new ShoppingCartItem(Key, price, quantity));
}
else
{
  item.Quantity = item.Quantity + quantity;
}

Strongly typed session shopping cart object that is extensible and allows you to do what you'd want and more. It can also be accessed by other parts of your application to show the number of items in the cart and a subtotal for an area, say at the top of your application to show a small preview of the shopping cart status.

于 2012-10-20T18:50:07.287 回答
1

在您的ShoppingCart课程中,您可以添加一个名为IncreaseQuantity(int productID)(和一个DecreaseQuantity方法)的方法。

public void IncreaseQuantity(int productID)
{
   int indexOfProduct = theCart.IndexOfKey(productID);

   if(indexOfProduct != -1)
   {
       this.theCart[indexOfProduct].quantityOrdered++;
   }
}

然后从您的会话中调用该方法

ShoppingCart cart = (ShoppingCart)Session["cart"];

if (cart.keyExists(int.Parse(productID.Text)))
{
    //can store the parsed int in a variable instead to prevent...
    //having to parse twice.
    cart.IncreaseQuantity(int.Parse(productID.Text));    
}
于 2012-10-20T18:45:44.277 回答
0

一种方法是将数量保持为每个 OrderItem 的一部分,然后通过枚举每个单独的 OrderItem 数量来获取购物车的总数。但是每个 OrderItem ID 必须只出现一次 ShoppingCart。

例如,在 ShoppingCart 中添加一个方法,例如

    public OrderItem Retrieve(int id)
    {
        return theCart[id] as OrderItem;
    }

然后如果购物车已经包含相同的产品 ID

    OrderItem orderItem = cart.Retrieve(1);
    item.QuantityOrdered += 1;

最后将更新后的购物车对象分配给 Session 变量。

另一种实现方法是在 ShoppingCart 中添加另一个 OrderItem 并维护按 OrderItem Id 分组的计数

于 2012-10-20T18:31:54.407 回答
0

我认为没有办法。

是什么让您需要重新创建对象?
是性能,还是保持代码干净?

如果是性能问题:
考虑在 Session 上为每个项目保存一个单独的对象,如下所示 -

int itemID = int.Parse(productID.Text);
int productQuantity = Session["item_number_" + itemID];

如果这是保持代码清洁的问题:
考虑将所有Session逻辑放在一个属性中:

public ShoppingCart SessionCart
{
    get
    {
        if (Session["cart"] == null)
            return new ShoppingCart();
        else
            return (ShoppingCart)Session["cart"];
    }
    set
    {
        Session["cart"] = value;
    }
}
于 2012-10-20T18:38:21.037 回答