分层更新

时间:2016-05-21 15:31:47

标签: c# linq

我在内存中有一个产品(类)列表,每个产品都可以有一个子产品列表(可以是空的)。有没有办法更新产品的库存(属性)数量和所有事件。

因此,例如,如果产品已售出但也作为另一产品的捆绑包的一部分出现,那么这两个数量将减少1个。

2 个答案:

答案 0 :(得分:0)

如果树的深度仅为1(子产品不能包含子产品),您可以使用着名的SelectMany

  

将序列的每个元素投影到IEnumerable并展平   得到的序列成一个序列。

List<Product> products = new List<Product>();

var allProductsWithSubs = (from p in products.SelectMany(x => x.SubProducts).Concat(products)
                            group p by p.ProductID into grp
                            select new
                            {
                                ProductID = grp.Key,
                                Quantity = grp.Sum(x => x.Quantity)
                            }).ToList();

public class Product
{
    public int ProductID { set; get; }
    public double Quantity { set; get; }
    public List<Product> SubProducts { set; get; }
}

答案 1 :(得分:0)

每次捆绑包中包含的任何项目的数量发生变化时,捆绑产品都可以重新计算数量。可以使用事件执行更新。

class Product
{
    public int Quantity 
    { 
        get { return _quantity}; 
        set 
        { 
            if (_quantity != value) 
            {
               _quantity = value; 
               OnQuantityChanged();
            }
        }
    }

    protected virtual void OnQuantityChanged()
    {
        var handler = QuantityChanged;
        if (handler != null) handler(this, EventArgs.Empty);
    }   

    int _quantity; 

    public event EventHandler QuantityChanged;   
}

class BundleProduct: Product
{
     public class BundleItem 
     {
        public BundleItem(Product product, int requiredQuantity)
        {
           this.Product = product;
           this.RequiredQuantity = requiredQuantity;
        }
        public int Quanity
        {
             get {return Product.Quantity / RequiredQuantity; }
        }

        public readonly Product Product;
        public readonly int RequiredQuantity;  
     }

     public IReadOnlyList<BundleItem> Items 
     {
        get {return _items;
     }  

     public void AddItem(Product product, int requiredQuantity)
     {
        var item = new BundleItem(product, requiredQuantity);
        _items.Add(item);
        product.QuantityChanged += ItemQuantityChanged;
        RecaclulateQuantity(); 
     }


     void RecalculateQuantity()
     {

         if (_updating)  return false; 

         _updating = true;
         try
         {
            // The quantity of a bundle is derived from 
            // availability of items it contains   
            int available = 0;

            if (_items.Count != 0)
            {
                available = _items[0].Quantity;  
                for(int i = 1; i < _items.Count; ++i)
                {
                   available = Math.Min(available, _items[i].Quanity);
                }  
            }
            this.Quantity = available;
         }
         finally
         {
             _updating = false;
         }
     }        

     void ItemQuantityChanged(object sender, EventArgs e)
     {
         RecalculateQuantity();
     }

     bool _updating; 
     List<Product> _items;

}