我有一个有三个属性的类:
class PriceCondition
{
public Product SalesCode {...}
public ControlDate Condition {...}
public PriceDetail Pricing {...}
}
Run Code Online (Sandbox Code Playgroud)
任何实例PriceCondition只能有一个SalesCode或一个Condition.如果Condition被选中,则Pricing需要,但这与此讨论无关.
作为一个相对较差的程序员,我最初尝试以下方法:
public Product SalesCode
{
get { return _salesCode; }
set
{
this.Condition = null;
_salesCode = value;
}
}
public ControlDate Condition
{
get { return _cond; }
set
{
this.SalesCode = null;
_cond = value;
}
}
Run Code Online (Sandbox Code Playgroud)
事后看来,很明显为什么会造成堆栈溢出.寻找正确的方法,我找到了关于XORing a的这个SO答案List,但是我无法弄清楚如何将其应用于我正在尝试做的事情,因为这Except是一种IEnumerable方法,而我没有使用List<T>或类似的东西.
如何确保任何时候只设置其中一个属性?我可以var CodeOrCondition在构造函数中传入一个参数,typeof用来确定它是什么,然后适当地分配它?我只是理解我刚才所说的内容,因此在我开始编写代码之前先了解一下这是否有效.
更新:
在答案中找到了极好的帮助后,我最终得到了这样的结论:
public class PriceCondition
{
#region Constructor
/// <summary>Create an empty PriceCondition.
/// </summary>
/// <remarks>An empty constructor is required for EntityFramework.</remarks>
public PriceCondition();
/// <summary>Create a PriceCondition that uses a Sales Code.
/// </summary>
/// <param name="salesCode">The Product to use.</param>
public PriceCondition(Product salesCode)
{
SalesCode = salesCode;
Condition = null;
Pricing = null;
}
/// <summary>Create a PriceCondition that uses a DateControl and Price (e.g. "0D7")
/// </summary>
/// <param name="dateControl">The DateControl Condition to use.</param>
/// <param name="price">The PriceDetail to use.</param>
public PriceCondition(Condition dateControl, PriceDetail price)
{
SalesCode = null;
Condition = dateControl;
Pricing = price;
}
#endregion
....
}
Run Code Online (Sandbox Code Playgroud)
第二次更新:
EntityFramework阻碍了我.我知道它需要空构造函数,但没有意识到原因的深度.我们发现使用private set是保持EF不会从数据库中填充对象.至少那是它的样子.我们在DBInitializer中持久保存数据,但是PriceCondition当我们尝试使用它时,信息没有被加载.简单的答案似乎是将setter重新放回标准的后备存储方法,并依赖于业务逻辑层,从不设置a SalesCode和a ControlDate相同PriceCondition.但现在这也没有用.我们会更多地抨击它,但任何建议都会非常感激.
设置支持变量而不是属性:
public Product SalesCode
{
get { return _salesCode; }
set
{
_cond = null;
_salesCode = value;
}
}
public ControlDate Condition
{
get { return _cond; }
set
{
_salesCode = null;
_cond = value;
}
}
Run Code Online (Sandbox Code Playgroud)
我个人喜欢的另一种方法是创建一个不可变对象,并为可能的配置提供构造函数:
class PriceCondition {
public Product SalesCode { get; private set; }
public ControlDate Condition { get; private set; }
public PriceDetail Pricing { get; private set; }
public PriceCondition(Product salesCode) {
SalesCode = salesCode;
Condition = null;
Pricing = null;
}
public PriceCondition(ControlDate condition, PriceDetail pricing) {
SalesCode = null;
Condition = condition;
Pricing = pricing;
}
}
Run Code Online (Sandbox Code Playgroud)
(您还应该验证构造函数中的参数,但这显示了原理.)