Подходящий способ обработки состояний объекта? - PullRequest
0 голосов
/ 15 декабря 2011

В настоящее время мы разрабатываем приложение (C #, .Net 4.0), которое требует обработки различных ресурсов.Чтобы отслеживать состояние актива, мы разработали класс «AssetState», который возвращает различные состояния, в которых актив может находиться:

/// <summary>
/// Represents the states an asset can be in.
/// </summary>
public class AssetState
{
    /// <summary>
    /// Initializes a new instance of the <see cref="AssetState"/> class.
    /// </summary>
    public AssetState()
    {
    }

    #region Properties

    /// <summary>
    /// Gets a normal asset state.
    /// </summary>
    public static AssetState None
    {
        get
        {
            return new AssetState();
        }
    }

    /// <summary>
    /// Gets a dirty asset state.
    /// </summary>
    public static AssetState Dirty
    {
        get
        {
            return new AssetState();
        }
    }

    (etc...)

    #endregion Properties

    #region Methods

    /// <summary>
    /// Overloaded operator used to combine two states into a new one.
    /// </summary>
    /// <param name="leftOperandState">The left operand in the equation.</param>
    /// <param name="rightOperandState">The right operand in the equation.</param>
    /// <returns>A new asset state, which is the AND combination of both operands, in the form of a list of states.</returns>
    public static List<AssetState> operator &(AssetState leftOperandState, AssetState rightOperandState)
    {
        if (leftOperandState == None && rightOperandState != None)
        {
            return new List<AssetState> { rightOperandState };
        }

        if (leftOperandState != None && rightOperandState == None)
        {
            return new List<AssetState> { leftOperandState };
        }

        if (leftOperandState == None && rightOperandState == None)
        {
            return new List<AssetState> { leftOperandState };
        }

        return new List<AssetState> { leftOperandState, rightOperandState };
    }

    /// <summary>
    /// Overloaded operator used to combine two states into a new one.
    /// </summary>
    /// <param name="leftOperandStates">The left operand in the equation.</param>
    /// <param name="rightOperandState">The right operand in the equation.</param>
    /// <returns>A new asset state, which is the AND combination of both operands, in the form of a list of states.</returns>
    public static List<AssetState> operator &(List<AssetState> leftOperandStates, AssetState rightOperandState)
    {
        var newAssetState = new List<AssetState>();   

        newAssetState.AddRange(leftOperandStates);
        newAssetState.Add(rightOperandState);

        return newAssetState;
    }

    #endregion Methods
}

Класс «Asset» будет содержать список AssetStates.Таким образом, элемент может быть помечен как «Грязный» и «CheckedOut», например.Когда нам нужно определить состояние актива, мы просто перебираем этот список и определяем, присутствует ли конкретное состояние (или набор состояний).

In the Asset Class:

    /// <summary>
    /// Method which determines if the asset is in a particular state.
    /// </summary>
    public bool IsInState(AssetState assetState)
    {
        return States.Contains(assetState);
    }

    /// <summary>
    /// Method which determines if the asset is in a particular combination of states.
    /// </summary>
    public bool IsInStates(IEnumerable<AssetState> assetStates)
    {
        if (assetStates == null)
        {
            throw new ArgumentNullException("assetStates");
        }

        // Determine if this asset is in all the states requested.
        return assetStates.All(assetState => assetState != null && this.IsInState(assetState));
    }

Есть ли лучший способ решения этой проблемы?Есть ли какие-либо серьезные подводные камни в разработанной нами системе, которую мы упустили из виду?(учитывая, что код здесь не окончательный, а черновой).

Ответы [ 2 ]

5 голосов
/ 15 декабря 2011

Похоже, вам было бы лучше использовать enum с атрибутом Flags. Взгляните здесь .

С атрибутом Flags вы сможете использовать & и | операторы. Вот пример:

// make a dirty & checked-out state
AssetState state = AssetState.Dirty | AssetState.CheckedOut;

// check if state contains Dirty
if ((state & AssetState.Dirty) != 0)
{
    // handle the dirty state
}

Будьте осторожны, какие значения вы присваиваете своему перечислению. Они должны быть 1, 2, 4, 8, 16 и т. Д. В противном случае вы не сможете правильно их объединить с помощью логических операторов.

3 голосов
/ 15 декабря 2011

Для объединения небольшого числа возможных состояний используйте enum вместо класса.

[Flags]
enum AssetState
{
    None = 0,
    Dirty = 1,
    CheckedOut = 2,
    RequiresAudit = 4
}
//Create new state for checked out and requires audit
AssetState state = AssetState.CheckedOut | AssetState.RequiresAudit;
//Set dirty without changing rest of state:
state |= AssetState.Dirty;
//Check if is "dirty":
bool isDirty = (state & AssetState.Dirty) != AssetState.None;
//Check if is "dirty" alternative method:
bool isDirty = state.HasFlag(AssetState.Dirty);

Вы также можете добавить значения для общих комбинаций к определению перечисления, например CheckedOutAndDity = 3

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...