在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-更改可以通过首先发布当前版本来完成。有这种情况可能是个好主意。(我将把它添加到代码中)。