如何在C#中创建互斥属性

J.D*_*Ray 3 c#

我有一个有三个属性的类:

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.但现在这也没有用.我们会更多地抨击它,但任何建议都会非常感激.

Guf*_*ffa 6

设置支持变量而不是属性:

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)

(您还应该验证构造函数中的参数,但这显示了原理.)