在我的Silverlight 4项目中,我有一个实现界面的简单类,如:
public interface IMyClass
{
string Name { get; set; }
anyotherclass Value { get; set; }
}
父类包含一系列IMyClass元素,如:
public class ParentClass
{
ObservableCollection<IMyClass> Children { get; }
}
现在我想确保,IMyClass.Name在Children集合中是唯一的。用户可以更改IMyClass.Name - 所以我需要验证名称是否已经在集合中。我想使用Silverlight异常和验证机制,我的XAML文本框看起来像:
<TextBox Text="{Binding
ValidatesOnExceptions=true,
NotifyOnValidationError=true,
Mode=TwoWay,
Path=Name}"/>
所以我需要检查Name属性的setter,如:
public string Name
{
get { return _name; }
set
{
if (value == _name)
return;
if (CollectionAlreadyContainsName(this, value))
throw new ArgumentException("The name already exists");
else
_name = value;
OnPropertyChanged("Name");
}
}
问题出现了:CollectionAlreadyContainsName需要知道集合,但在IMyClass对象中,我不知道我在哪个集合中。我需要保持对父母的引用,如
public interface IMyClass
{
string Name { get; set; }
anyotherclass Value { get; set; }
ParentClass Parent { get; }
}
由于交叉引用而对我不好,并且需要确保父项始终设置正确。所以我寻找另一种方法来做到这一点。一个想法是让ParentClass监听IMyClass的NameChanged事件,并在必要时恢复名称更改。但是这不适用于提到的Silverlight异常和验证机制。
任何想法如何解决这个问题?
提前致谢,
弗兰克
答案 0 :(得分:0)
你给了IMyClass错误的责任。它不知道该集合,它不应该。
集合类的职责是仅添加名称不同的对象。
因此,覆盖/创建一个执行此操作的add方法,并使该名称为readonly或订阅集合中名称的更改,并在那里抛出错误。
修改强>
不要还原该属性。这不是该系列的责任。
答案 1 :(得分:0)
这里的问题是它并不那么简单;一个对象可以由零个,一个或多个多个集合引用。假设有一个很好的OO理由让孩子知道父母(实际上非常罕见),你需要决定你需要支持哪一个。我不会在这里使用事件,因为事件也多播,可能会让人感到困惑。
如果它是一个强大的父/子关系,那么无论如何添加一个父属性,但你应该强制执行它 - 即你不能不小心添加一个已经是孩子的对象另一个集合,并添加它应该设置父。
您还应确保只有一个Add api - 即您是否在对象上调用方法?还是收藏品?要么有效,要么有一种方法可以避免混淆。您几乎肯定需要一个自定义集合来执行此操作,以避免默认的Add实现。
答案 2 :(得分:0)
接口中不需要Parent
属性,只是实现类中的数据成员。将父项传递给构造函数。