Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在两个对象之间实现临时独占关系_C#_Oop - Fatal编程技术网

C# 在两个对象之间实现临时独占关系

C# 在两个对象之间实现临时独占关系,c#,oop,C#,Oop,我需要实现两个对象所有者和项目之间的关系,这样所有者拥有0..1个项目,并且每个项目一次只能由一个所有者拥有 类别定义如下: 类项目 { } 类所有者 { 公共项项{get;set;} } 关键是,当一个所有者拥有一个分配给它的项时,任何其他所有者都会失去对该项的所有权(并且其项引用被设置为null) 请参见以下示例代码: Owner-owner1=新所有者(); Owner owner2=新所有者(); Item anItem=新项(); //现在owner1.item和owner2.ite

我需要实现两个对象所有者和项目之间的关系,这样所有者拥有0..1个项目,并且每个项目一次只能由一个所有者拥有

类别定义如下:

类项目
{
}
类所有者
{
公共项项{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()
      逻辑位于
      Owner
      类中,那么它就不必位于该类中。从DDD的角度来看,这是有意义的,但您也可以将其放在单独的验证对象或存储库中。这一切都取决于你的架构,你的问题并没有透露足够的信息让我做出结论性的回答
  • 如果您想变得聪明,并给这两个类彼此提供一个引用,那么当每个项尝试更新其引用项的属性时,请注意无限递归。这是可以做到的,但我建议尽量避免,原因有二:
    • 它减少了您必须进行的数据处理
    • 它可以防止您的数据不一致或自相矛盾的可能性(例如,指代不同所有者的项目的所有者)

这可以在设定器中完成。您可能需要
类中的
所有者
属性:

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

你有数据库吗?或者它是一个没有数据库的代码?这听起来像是一个错误。你的最终目标是什么?你为什么要这么做?