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

时间:2015-03-31 19:40:33

标签: c#

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

class PriceCondition
{
    public Product SalesCode {...}
    public ControlDate Condition {...}
    public PriceDetail Pricing {...}
}

PriceCondition的任何实例只能有SalesCodeCondition。如果选择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; 
        }
    }

事后看来,很明显为什么会造成堆栈溢出。正在寻找正确的方法,我找到this SO answer about XORing a 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
....
}

第二次更新:

EntityFramework妨碍了我。我知道它需要空构造函数,但没有意识到原因的深度。我们发现使用private set可以防止EF从数据库中填充对象。至少那是它的样子。我们在 DBInitializer 中保留了数据,但是当我们尝试使用它时,信息没有加载到PriceCondition。简单的答案似乎是将设置者放回标准的后备存储方法,并依赖于业务逻辑层,从不在同一SalesCode上设置ControlDatePriceCondition。但现在这也没有用。我们会更多地抨击它,但任何建议都会非常感激。

3 个答案:

答案 0 :(得分:6)

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

public Product SalesCode
{
    get { return _salesCode; }
    set 
    {
        _cond = null;
        _salesCode = value; 
    }
}

public ControlDate Condition
{
    get { return _cond; }
    set 
    {
        _salesCode = null;
        _cond = value; 
    }
}

我个人喜欢的另一种方法是创建一个不可变对象,并为可能的配置提供构造函数:

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;
  }

}

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

答案 1 :(得分:0)

对您的尝试只做一个小改动就可以防止堆栈溢出:

public Product SalesCode
{
    get { return _salesCode; }
    set 
    {

<强>

        if (value != null)

            this.Condition = null;
        _salesCode = value; 
    }
}

答案 2 :(得分:0)

我可以想到这样的事情:

    public class PriceCondition
{
    private Product m_Product;
    private ControlDate m_ControlDate;

    public PriceCondition(Product product)
    {
        m_Product = product;
    }

    public PriceCondition(ControlDate controlDate)
    {
        m_ControlDate = controlDate;
    }

    public Product SalesCode
    {
        get { return m_product; }
    }

    public ControlDate Condition
    {
        get { return m_ControlDate; }
    }
}

两个构造函数将始终保证其中一个属性未设置(它实际上为null)。 使用两个只读属性,您始终可以看到设置了哪一个(由于构造函数,将设置其中一个)