我需要实现两个对象Owner和Item之间的关系,以便所有者拥有0..1个项目,并且每个项目一次只能由一个所有者拥有。
类定义如下:
class Item
{
}
class Owner
{
public Item item { get; set; }
}
问题在于,当所有者分配了一个项目时,任何其他所有者都将失去对该项目的所有权(并且其项目引用设置为null)。
请参见以下示例代码:
Owner owner1 = new Owner();
Owner owner2 = new Owner();
Item anItem = new Item();
// right now owner1.item and owner2.item are both null
owner1.item = anItem;
// owner1.item is anItem and owner2.item is null
owner2.item = anItem;
// owner1.item is null and owner2.item is anItem
什么是实施此行为的有效且正确的方法?
很抱歉,如果我使用的术语不正确,也许是由于我对此知识的了解不足,所以我还没有找到解决方案。
答案 0 :(得分:1)
问题在于,当所有者分配了一个项目时,任何其他所有者都将失去对该项目的所有权(并且其项目引用设置为null)。
最简单的方法是反转关系(即谁存储对另一个的引用)
public Item
{
public Owner Owner { get; set; }
}
您也可以使用Owner.Id
或类似有效的标识符,但答案仍然相同。
这样,每个项目只有一个“框”可以注册所有者。有效进行的任何注册都将覆盖现有所有者,这就是您想要的。
当然,由于您希望关系基本上是对称的,因此可以通过在Owner
类中使用引用来实现相同的目的。哪种方法都没关系,请使用最适合您的方法(您是将项目分配给所有者,还是将所有者分配给项目?这是语义上的差异,而不是技术上的差异)>
我需要实现两个对象Owner和Item之间的关系,以便所有者拥有0..1个项目,并且每个项目一次只能由一个所有者拥有。
这不再那么容易解决,因为如果您希望将此逻辑应用于关系的两侧,则无法自动执行此行为。
要维护关系两端的唯一性(无论是否可以为空),您将必须使用显式业务逻辑来确认唯一性得到保持。
这实际上没有窍门。每当有人要添加新的所有者-项目关系时,就必须强制执行此检查。这样的例子之一可能是:
public class Item
{
public Owner Owner { get; private set }
public void SetOwner(Owner owner)
{
if(!owner.OwnsItem)
{
this.Owner = owner;
}
else
{
//Do nothing, throw an exception, log a message, ...
}
}
}
public class Owner
{
public bool OwnsItem()
{
return ListOfAllItems.Any(item => item.Owner == this);
}
}
注释
owner
参数的空检查。目前尚不清楚物品是否曾被放弃。如果与您的案例有关,请添加它。ListOfAllItems
确实提供了您所说的内容。
OwnsItem()
逻辑不出现在Owner
类中,则不会。从DDD的角度来看,这样做很有意义,但是您也可以将其放在单独的验证对象或存储库中。这完全取决于您的体系结构,您的问题还不足以让我最终得出结论。答案 1 :(得分:0)
这可以在设置器中完成。在Owner
类中可能需要一个Item
属性:
在Item
类中:
class Item
{
public string Name { get; set; }
private Owner owner = null;
public Owner Owner
{
get { return owner; }
set
{
owner = value;
Console.WriteLine($"I am {Name} and I am now owned by {(owner != null ? owner.Name : "no one")}");
}
}
}
现在,我们可以在Owner
类中进行相同的操作:
class Owner
{
public string Name { get; set; }
private Item item = null;
public Item Item
{
get { return item; }
set
{
if (value != null)
{
value.Owner = this;
}
item = value;
Console.WriteLine($"I am {Name} and I now own {(item != null ? item.Name : "no one")}");
}
}
}
但这只是将关系设置为双向!这不会删除另一个对象的所有权!
对,但是现在我们可以使用item.Owner
删除旧所有者和商品之间的关系,例如:
class Owner
{
public string Name { get; set; }
private Item item = null;
public Item Item
{
get { return item; }
set
{
if (value != null)
{
if (value.Owner != null)
{
value.Owner.Item = null;
}
value.Owner = this;
}
item = value;
Console.WriteLine($"I am {Name} and I now own {(item != null ? item.Name : "no one")}");
}
}
}
但是如果我要使用 ,owner.Item = null
该项目也需要删除其所有者! < / strong>
对,如果值是item.Owner
,我们可以使用null
删除关系
class Owner
{
public string Name { get; set; }
private Item item = null;
public Item Item
{
get { return item; }
set
{
if (value != null)
{
if (value.Owner != null)
{
value.Owner.Item = null;
}
value.Owner = this;
}
else
{
if (item != null)
{
item.Owner = null;
}
}
item = value;
Console.WriteLine($"I am {Name} and I now own {(item != null ? item.Name : "no one")}");
}
}
}
我们现在可以对其进行测试:
Owner owner1 = new Owner { Name = "owner1" };
Owner owner2 = new Owner { Name = "owner2" };
Item anItem = new Item { Name = "item1" };
owner1.Item = anItem;
Console.WriteLine("---------------------------------");
owner2.Item = anItem;
输出
I am item1 and I am now owned by owner1
I am owner1 and I now own item1
---------------------------------
I am item1 and I am now owned by no one
I am owner1 and I now own no one
I am item1 and I am now owned by owner2
I am owner2 and I now own item1