Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.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中只将一个对象作为参数传递一次#_C#_Class_Design Patterns - Fatal编程技术网

在c#中实现双向关联:如何在c中只将一个对象作为参数传递一次#

在c#中实现双向关联:如何在c中只将一个对象作为参数传递一次#,c#,class,design-patterns,C#,Class,Design Patterns,我希望正确表达我的问题(如果没有,请帮助我更好地命名) ,为了清楚起见,请看一下我的代码 我的问题出现在使用factory类的第一个构造函数时 class Program { static void Main(string[] args) { Person oPerson1=new Person("Jon",30); factory oFactory1=new Factory("f1",oPerson1); factory oF

我希望正确表达我的问题(如果没有,请帮助我更好地命名) ,为了清楚起见,请看一下我的代码


我的问题出现在使用factory类的第一个构造函数时

class Program
{
    static void Main(string[] args)
    {
        Person oPerson1=new Person("Jon",30);

        factory oFactory1=new Factory("f1",oPerson1);
        factory oFactory2=new Factory("f2",oPerson1);
        factory oFactory3=new Factory("f3",oPerson1);
        factory oFactory4=new Factory("f4",oPerson1);
        ...
    }
}
正如您在这个构造函数中看到的我可以多次使用一个人对象(作为管理者) ,事实上它可以使用很多次,没有什么可以阻止我。那个 意思是一个人可以管理许多工厂,我不想要它。我想要一个人可以 只管理一家工厂,这怎么可能


为了解决这个问题,我想到了一些解决办法。
1-删除该构造函数并仅使用另一个。(但我正在寻找更好的解决方案,我希望使用该构造函数。)
2-在运行时抛出一个我讨厌的异常


据我所知,c#编译器无法阻止对象多次传递。
我应该在课堂设计上做些改变吗? 你的建议是什么?最好的解决方案是什么?非常感谢您的建议

编辑:我们的业务逻辑

每个工厂都有一个经理,没有经理的工厂是没有意义的

一个人可以是经理


人(1..1)---(0..1)工厂

答案在您的代码中:

set
{
    _manager = value;
    if (_manager.WorkPlace!=this)
    {
        _manager.WorkPlace = this;
    }
}
替换为

set
{
    if (value == null)  // Edit: Add manager release capability to change factories
    {
        if(_manager != null)
           _manager.WorkPlace = null;

        _manager = null;
    }
    else if (value.WorkPlace == null)
    {
        _manager = value;
        _manager.WorkPlace = this;
    }
    else
        throw new ArgumentException();
}

答案在您的代码中:

set
{
    _manager = value;
    if (_manager.WorkPlace!=this)
    {
        _manager.WorkPlace = this;
    }
}
替换为

set
{
    if (value == null)  // Edit: Add manager release capability to change factories
    {
        if(_manager != null)
           _manager.WorkPlace = null;

        _manager = null;
    }
    else if (value.WorkPlace == null)
    {
        _manager = value;
        _manager.WorkPlace = this;
    }
    else
        throw new ArgumentException();
}
我对设定器使用以下“微模式”:

    public Person Manager 
    {
        get
        {
            return (_manager );
        }
        set
        {
            if (_manager != null)
            {
                _manager.WorkPlace = null;
            }

            _manager = value;

            if (_manager != null)
            {
                _manager.WorkPlace = this;
            }
        }
现在,每当您将经理与工厂关联时,它的旧经理将自动与工厂解除关联

现在,这并不妨碍您将经理重新分配到工厂。但它将确保指针始终彼此同步

我从Martin Fowlers重构中学到了这个技巧。可以在网上找到该技术的参考资料。

我对设定器使用以下“微模式”:

    public Person Manager 
    {
        get
        {
            return (_manager );
        }
        set
        {
            if (_manager != null)
            {
                _manager.WorkPlace = null;
            }

            _manager = value;

            if (_manager != null)
            {
                _manager.WorkPlace = this;
            }
        }
现在,每当您将经理与工厂关联时,它的旧经理将自动与工厂解除关联

现在,这并不妨碍您将经理重新分配到工厂。但它将确保指针始终彼此同步


我从Martin Fowlers重构中学到了这个技巧。可以找到该技术的在线参考。

尽管您不喜欢它,但在构造函数中抛出异常会提前通知您有错误。你还需要确保这个人不是经理

public Factory(string name, Person manager)
{   if (Manager.WorkPlace != null && Manager.WorkPlace.Manager==manager)
    { 
        var errmsg = "Cannot pass an existing manager to Factory constructor.";
        throw new ArgumentException("manager",errmsg);
    }

    Name = name;
    Manager = manager;
    Manager.WorkPlace = this;
}

尽管您讨厌它,但在构造函数中抛出异常将提前通知您有错误。你还需要确保这个人不是经理

public Factory(string name, Person manager)
{   if (Manager.WorkPlace != null && Manager.WorkPlace.Manager==manager)
    { 
        var errmsg = "Cannot pass an existing manager to Factory constructor.";
        throw new ArgumentException("manager",errmsg);
    }

    Name = name;
    Manager = manager;
    Manager.WorkPlace = this;
}

使用静态代码关系比使用命令检查更好地建模关系。这将使编译器能够帮助您强制执行关系

从工厂中删除管理器并将工厂添加到管理器:

public class Manager : Person
{
    public Manager(Factory factory)
}

通过这种方式,经理只能管理一个工厂。

使用静态代码关系建模比使用命令检查更好。这将使编译器能够帮助您强制执行关系

从工厂中删除管理器并将工厂添加到管理器:

public class Manager : Person
{
    public Manager(Factory factory)
}
这样,经理只能管理一个工厂…

一个“单元”有一个“项目”;一个“项目”有一个“单元”。如果你更新了其中一个;另一个也应该更新。所以在Cell中,我们有一个类似于:

    public Item CurrentItem
    {
        get { return _currentItem; }
        set
        {
            if (_currentItem == value) return;
            var oldItem = _currentItem;
            _currentItem = value;
            if (oldItem != null && oldItem.CurrentCell == this)
            {
                oldItem.CurrentCell = null;
            }
            if (value != null)
            {
                value.CurrentCell = this;
            }
        }
    }
在相对站点(项目中),我们拥有以下属性:

    public Cell CurrentCell
    {
        get { return _currentCell; }
        set
        {
            if (_currentCell == value) return;
            var oldCell = _currentCell;
            _currentCell = value;
            if (oldCell != null && oldCell.CurrentItem == this)
            {
                oldCell.CurrentItem = null;
            }
            if (value != null)
            {
                value.CurrentItem = this;
            }
        }
    }
“单元”有一个“项”;一个“项目”有一个“单元”。如果你更新了其中一个;另一个也应该更新。所以在Cell中,我们有一个类似于:

    public Item CurrentItem
    {
        get { return _currentItem; }
        set
        {
            if (_currentItem == value) return;
            var oldItem = _currentItem;
            _currentItem = value;
            if (oldItem != null && oldItem.CurrentCell == this)
            {
                oldItem.CurrentCell = null;
            }
            if (value != null)
            {
                value.CurrentCell = this;
            }
        }
    }
在相对站点(项目中),我们拥有以下属性:

    public Cell CurrentCell
    {
        get { return _currentCell; }
        set
        {
            if (_currentCell == value) return;
            var oldCell = _currentCell;
            _currentCell = value;
            if (oldCell != null && oldCell.CurrentItem == this)
            {
                oldCell.CurrentItem = null;
            }
            if (value != null)
            {
                value.CurrentItem = this;
            }
        }
    }

这是一个多大的问题?你不能简单地。。。不是吗?在构造函数中抛出一个异常是你最接近的问题。这是一个多大的问题?你不能简单地。。。不这样做?在构造函数中抛出异常是最接近的bet1。我们必须在集合的第一行为_manager赋值,否则将引发“对象空引用异常”。2-想象你在使用这门课时,当你经常看到一个异常时,你的感觉是什么。3-正如布罗克所说,以这种方式,我们在更换工厂经理时会遇到问题,反之亦然。谢谢1-谢谢,修复了。2-由于这是问题的限制,因此将经理分配到其他工厂是错误的。但它应该在文档中。或者也可以使用代码契约在intellisense中实现它。3-更改可以通过首先发布当前版本来完成。有这种情况可能是个好主意。(我将把它添加到代码中)。1-我们必须在集合的第一行为_manager赋值,否则将引发“对象空引用异常”。2-想象你在使用这门课时,当你经常看到一个异常时,你的感觉是什么。3-正如布罗克所说,以这种方式,我们在更换工厂经理时会遇到问题,反之亦然。谢谢1-谢谢,修复了。2-由于这是问题的限制,因此将经理分配到其他工厂是错误的。但它应该在文档中。或者也可以使用代码契约在intellisense中实现它。3-更改可以通过首先发布当前版本来完成。有这种情况可能是个好主意。(我将把它添加到代码中)。