C# 在两个对象之间实现临时独占关系
我需要实现两个对象所有者和项目之间的关系,这样所有者拥有0..1个项目,并且每个项目一次只能由一个所有者拥有 类别定义如下:C# 在两个对象之间实现临时独占关系,c#,oop,C#,Oop,我需要实现两个对象所有者和项目之间的关系,这样所有者拥有0..1个项目,并且每个项目一次只能由一个所有者拥有 类别定义如下: 类项目 { } 类所有者 { 公共项项{get;set;} } 关键是,当一个所有者拥有一个分配给它的项时,任何其他所有者都会失去对该项的所有权(并且其项引用被设置为null) 请参见以下示例代码: Owner-owner1=新所有者(); Owner owner2=新所有者(); Item anItem=新项(); //现在owner1.item和owner2.ite
类项目
{
}
类所有者
{
公共项项{get;set;}
}
关键是,当一个所有者拥有一个分配给它的项时,任何其他所有者都会失去对该项的所有权(并且其项引用被设置为null)
请参见以下示例代码:
Owner-owner1=新所有者();
Owner owner2=新所有者();
Item anItem=新项();
//现在owner1.item和owner2.item都为空
owner1.item=anItem;
//owner1.item为anItem,owner2.item为null
owner2.item=anItem;
//owner1.item为空,owner2.item为anItem
实施这种行为的有效和正确的方法是什么
如果我没有使用正确的术语,我很抱歉,也许是因为我对它缺乏了解,我还没有找到解决方案
关键是,当一个所有者拥有一个分配给它的项时,任何其他所有者都会失去对该项的所有权(并且其项引用被设置为null)
实现这一点的最简单方法是颠倒关系(即谁存储对另一个的引用)
您也可以使用Owner.Id
或类似的有效标识符,但答案保持不变
这样,每个项目只有一个“框”来注册所有者。任何发生的注册都会有效地覆盖您想要的现有所有者
当然,由于您希望关系基本上是对称的,因此可以通过在Owner
类中使用引用来实现同样的效果。你用哪种方式做并不重要,使用对你最有意义的方式(你是将项目分配给所有者,还是将所有者分配给项目?这是语义上的差异,而不是技术上的差异)
我需要实现两个对象所有者和项目之间的关系,这样所有者拥有0..1个项目,并且每个项目一次只能由一个所有者拥有
这不再那么容易修复,因为如果您希望在关系的两侧应用此逻辑,则无法自动执行此行为
为了维护关系两端的唯一性(不管是否为null),您必须使用明确的业务逻辑来确认是否支持唯一性
这真的没有什么诀窍。每当有人想要添加新的所有者项目关系时,就需要强制执行此检查。其中一个例子是:
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);
}
}
注释
- 我跳过了如何为所有者进行平等检查。很可能,您会检查一个ID值,但您的问题并没有明确说明这一点。使用任何适当的相等性检查
- 我还跳过了
参数的空检查。现在还不清楚一件物品是否被否认。如果它与您的案例相关,请添加它owner
- 这要求您可以访问所有项目的列表,以便查找所有权。您如何获得该列表在很大程度上取决于您如何存储数据,您在问题中没有提到这些数据。出于示例的目的,我假设
准确地给出了它所说的内容。ListOfAllItems
- 如果您不希望
逻辑位于OwnsItem()
类中,那么它就不必位于该类中。从DDD的角度来看,这是有意义的,但您也可以将其放在单独的验证对象或存储库中。这一切都取决于你的架构,你的问题并没有透露足够的信息让我做出结论性的回答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")}");
}
}
}
在类项中
:
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
该项目的所有者也需要删除强>
对,如果值为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
你有数据库吗?或者它是一个没有数据库的代码?这听起来像是一个错误。你的最终目标是什么?你为什么要这么做?