【发布时间】:2021-08-22 11:26:11
【问题描述】:
我正在构建一个 WPF 应用程序。假设我们有一个超级市场;两种类型的对象称为Customer 和Product。 Customer 对象存储了他在购物车中的 Products。我有两个字典,用于存储 Customer 和 Product 对象的实例(两者都是唯一的)。
测试数据
客户列表 (Dictionary<String,Customer>)
|客户|
| -------- |
|客户 A |
|客户 B |
产品列表 (Dictionary<String,Product>)
|产品|
| -------- |
|苹果 |
|香蕉 |
|西瓜|
|黄瓜|
| CustomerA |
|---|
| Apple |
| Banana |
| CustomerB |
|---|
| Apple |
| Watermelon |
我有一个Customer 类型的ObservableCollection CustomerList,我显示并使用它来修改我的Customers(和他们的Products)。我想实现以下内容:当我从ProductList 中删除产品Apple 时,我希望它从CustomerA 和CustomerB 的“购物车”中消失。我在想的是每个Customer 应该将产品存储为指向ProductList 所需索引的指针(我已经做了一些C++)。但是,当我在线阅读时,似乎指针在 C# 中是一个很大的禁忌。有没有容易做到这一点?当我从 ProductList 删除或修改产品使其“无法购买”时,我不想管理每个 Customer。
编辑:添加了要求,我还希望能够修改 Productlist 中的 Apple 产品(例如将其重命名为 Red Apples)并让客户 A 和客户 B“购物车”也相应更改。
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace ConsoleApp1
{
public class Customer : INotifyPropertyChanged
{
private string name;
public ObservableCollection<Product> Items { get; set; }
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
public Customer(string _name)
{
name = _name;
Items = new ObservableCollection<Product>();
}
public void AddItem(Product item)
{
Items.Add(item);
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyRaised(string propertyname)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
}
}
}
public class Product : INotifyPropertyChanged
{
private string name;
private Guid guid;
private double price;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
public Guid GUID
{
get
{
return guid;
}
set
{
guid = value;
}
}
public double Price
{
get
{
return price;
}
set
{
price = value;
}
}
public Product(string _name, double _price)
{
name = _name;
price = _price;
guid = Guid.NewGuid();
}
public void Modify(string _newname,double _price)
{
name = _newname;
price = _price;
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyRaised(string propertyname)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
}
}
}
public class MarketServices
{
// This will hold all my unique instances of Customer objects
public Dictionary<String, Customer> CustomerObjectsMainList_Services = new Dictionary<String, Customer>();
// This will hold all my unique instances of Product objects
public Dictionary<String, Product> ProductObjectsMainList_Services = new Dictionary<String, Product>();
// This will be used to display customers in a listview/datagrid and do modifications on it
// I want the objects in this observable collection to be "linked" or "point" to the instances in CustomerObjectsMainList_Services
// Such that if I modify any customername for example it would be reflected here too
// Also changing any product name or removing any product from ProductObjectsMainList_Services should be reflect in the "cart" of all customers
// in CustomerObjectsMainList_Services and CustomerObjectsList_Services
public ObservableCollection<Customer> CustomerObjectsList_Services = new ObservableCollection<Customer>();
public MarketServices()
{
this.CreateCustomers();
//Here I want to fill CustomerObjectsList_Services with the instances of customers in CustomerObjectsMainList_Services
foreach (var kvp in CustomerObjectsMainList_Services)
CustomerObjectsList_Services.Add(kvp.Value);
//Now if I delete a product from the ProductObjectsMainList_Services, will it get reflected on the Customer objects?
}
public void CreateCustomers()
{
CustomerObjectsMainList_Services.Add("CustomerA", new Customer("CustomerA"));
CustomerObjectsMainList_Services.Add("CustomerB", new Customer("CustomerB"));
ProductObjectsMainList_Services.Add("Apple", new Product("Apple",10));
ProductObjectsMainList_Services.Add("Banana", new Product("Banana",15));
ProductObjectsMainList_Services.Add("Watermelon", new Product("Watermelon",20));
ProductObjectsMainList_Services.Add("Cucumber", new Product("Cucumber",25));
CustomerObjectsMainList_Services["CustomerA"].AddItem(ProductObjectsMainList_Services["Apple"]);
CustomerObjectsMainList_Services["CustomerA"].AddItem(ProductObjectsMainList_Services["Banana"]);
CustomerObjectsMainList_Services["CustomerB"].AddItem(ProductObjectsMainList_Services["Apple"]);
CustomerObjectsMainList_Services["CustomerB"].AddItem(ProductObjectsMainList_Services["Watermelon"]);
}
}
class Program
{
public static void PrintCustomer(Customer customer)
{
foreach (var x in customer.Items)
{
Console.WriteLine("{0} {1} {2}", x.Name, x.Price,x.GUID);
}
}
static void Main(string[] args)
{
MarketServices test = new MarketServices();
test.CustomerObjectsList_Services.Add(test.CustomerObjectsMainList_Services["CustomerA"]);
test.CustomerObjectsList_Services.Add(test.CustomerObjectsMainList_Services["CustomerB"]);
Console.WriteLine("Printing Customer A objects");
PrintCustomer(test.CustomerObjectsMainList_Services["CustomerA"]);
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("Printing Customer B objects");
PrintCustomer(test.CustomerObjectsMainList_Services["CustomerA"]);
Console.WriteLine();
Console.WriteLine();
test.ProductObjectsMainList_Services["Apple"].Modify("Peaches",5);
Console.WriteLine("Printing Customer A objects after changing Apples to Peaches");
PrintCustomer(test.CustomerObjectsList_Services[0]);
test.ProductObjectsMainList_Services["Peaches"] = null;
Console.WriteLine("Printing Customer A objects after removing Peaches");
PrintCustomer(test.CustomerObjectsList_Services[0]);
}
}
}
Edit2:提供修改后的代码;如果我修改任何产品名称或价格,上述方法有效。但是,我不确定如何从 ProductObjectsMainList_Services 中“删除”产品并将其从所有在“购物车”中拥有该产品的客户中删除。
【问题讨论】:
-
嗯,这样做的一种方法是让产品成为带有布尔标志(例如“可用”)的单例(一个实例)。当您将其设置为 true 时,这不会删除该实例,但您可以在检查 bool 时从任何集合中忽略(或删除)该产品。
-
@zer0 将使其成为单例意味着我只能拥有一个产品对象(仅限 Apple?)
-
Singleton 表示特定类的一个实例。所以你可以创建一个 Apple 和 Banana 类。如果产品具有共享属性,请使用
IProduct之类的接口。例如,您的字典将更改为Dictionary<String,IProduct>。如果所有产品共享一些代码,您也可以在此处使用抽象基类。 -
@zer0 那是行不通的,因为我的产品列表可以动态更改。我可能会在运行时添加产品。我不能用 C++ 中的指针来做到这一点吗?
-
你可以很容易地在运行时创建单例(我会使用泛型,但不是必需的)。想要一个例子吗?是的,C# 可以使用指针,但现在您使用的是
unsafe代码。
标签: c#