假设示例:我有一个客户列表和内存中的产品列表。我希望能够访问每个客户购买的产品以及购买特定产品的客户:
class Customer
{
public List<Product> Products { get; set; }
}
class Product
{
public List<Customer> CustomersWhoBoughtThis { get; set; }
}
var customers = new List<Customer>();
var products = new List<Product>();
//add the customers
var customer1 = new Customer();
customers.Add(customer1);
var customer2 = new Customer();
customers.Add(customer2);
//add the products
var product1 = new Product();
products.Add(product1);
var product2 = new Product();
products.Add(product2);
//add a purchased product for customer1
customer1.Products.Add(product1);
//How do I get customer1 from product1?
foreach (var customerWhoBoughtProduct1 in product1.CustomersWhoBoughtThis)
{
//do something
}
我可以手动将客户添加到产品的CustomersWhoBoughtThis
列表中,但我觉得这很容易出错,因为您可能忘记在某个地方执行此操作。
这有更好的实施吗?也许是某种处理功能的包装类,但我不确定它是如何实现的。有什么建议吗?
由于
答案 0 :(得分:2)
您可以定义一些包装类,或者实现您自己的IList
接口,然后您可以实现自己的事件支持通知。然而,使用内置的东西要简单得多。我会使用BindingList<T>
,它有一个名为ListChanged
的事件,它允许您获得一些通知,包括项目添加通知。请尝试以下代码:
class Customer {
public Customer(){
Products = new BindingList<Product>();
Products.ListChanged += (s,e) => {
if(e.ListChangedType == ListChangedType.ItemAdded){
Products[e.NewIndex].CustomersWhoBoughtThis.Add(this);
}
};
}
public BindingList<Product> Products { get; set; }
}
答案 1 :(得分:2)
通常当我有一个循环关系时,我指定一个实体作为关系的“所有者”。所有者负责管理关系,因此该管理的任何代码都应该封装在其中。
在这种情况下,由于客户实际执行了操作(客户购买产品),因此最好是Customer类是关系所有者。
因此,Product类将是:
public class Product
{
//other product properties
//field for the customers list
private List<Customer> customers = new List<Customer>();
//read-only property for outside access
public IEnumerable<Customer> Customers
{
get { return customers; }
}
//internal method that will only be called by the customer class
internal void AddCustomer(Customer customer)
{
customers.Add(customer);
}
//internal method that will only be called by the customer class
internal void RemoveCustomer(Customer customer)
{
customers.Remove(customer);
}
}
并且客户将是:
public class Customer
{
//other customer properties
//field for the product list
private List<Product> products = new List<Product>();
//read-only property for outside access
public IEnumerable<Product> Products
{
get { return products; }
}
//public method, open to the world
public void BuyProduct(Product product)
{
products.Add(product);
product.AddCustomer(this);
}
//public method, open to the world
public void RemoveProduct(Product product)
{
products.Remove(product);
product.RemoveCustomer(this);
}
}
现在你这样做:
customer1.BuyProduct(product1);
并正确设置引用。此外,外部用户(来自其他程序集)将无法调用product1.AddCustomer
。
此外,值得注意的是,循环引用的序列化(对XML或JSON)是一个婊子,因为客户的产品的客户产品具有堆栈溢出异常。
答案 2 :(得分:1)
创建一个将执行两个操作的方法
void PairCustomerWithProduct(Customer customer, Product product)
{
customer.Products.Add(product);
product.CustomersWhoBoughtThis.Add(customer);
}
无论何时您需要将产品与客户配对,请调用此方法。
答案 3 :(得分:1)
我不会将List<T>
公开为public,而是返回一个数组或序列。公开添加/删除产品的方法。
class Customer
{
private List<Product> Products { get; set; }
public void AddProduct(Product product)
{
Products.Add(product);
if(!product.CustomersWhoBoughtThis.Contains(this))
product.CustomersWhoBoughtThis.Add(this);
}
public void RemoveProduct(Product product)
{
Products.Remove(product);
if(product.CustomersWhoBoughtThis.Contains(this))
product.CustomersWhoBoughtThis.Remove(this);
}
public IEnumerable<Product> GetProducts()
{
return Products;
}
}
答案 4 :(得分:0)
你可以这样试试,
Class Customer{listCustomer>}
- 持有客户信息 类产品{list} - 保留产品信息
再添加一个类来维护组合
Class Sale{ public Customer, public Product }
获得SoldProducts列表的另一个类
Class SoldProduct{ list<Sale> }
答案 5 :(得分:0)
做一个关系课。
注意:我没有包含错误处理,只是基本的想法。另请注意,关系类(对于一对多关系)可以很容易地变为通用关系,并可以重用于任何类型的关系。我把它弄为具体,以使其更清晰。
class Customer
{
public List<Products> Products
{
get { return CustomerProductRelationship.CustomerProducts[this];}
set
{
CustomerProductRelationship.AddPair(value, this);
}
}
class Product
{
public List<Products> Products
{
get { return CustomerProductRelationship.ProductCustomers[this];}
set
{
CustomerProductRelationship.AddPair(this, value);
}
}
}
static class CustomerProductRelationship
{
public static Dictionary<Customer, List<Product>> CustomerProducts;
public static Dictionary<Product, List<Customer> ProductCustomers;
public static AddPair(Product product, Customer customer)
{
if (!CustomerProducts.Contains(customer))
CustomerProducts.Add(customer, new List<Product>);
CustomerProducts[customer].Add(product);
if (!ProductCustomers.Contains(product))
ProductCustomers.Add(product, new List<Customers>);
CustomerProducts[product].Add(customer);
}
}