Синхронизируйте два свойства между двумя классами, не раскрывая сеттеры в C #

1

Таким образом, мне нужен сеттер или метод, который доступен только одному (или нескольким другим) классам. Насколько я знаю, это распространено на некоторых других языках в качестве классов друзей. Я попытался упростить приведенный ниже пример. Это не настоящий случай, и это немного сложнее. Но я должен убедиться, что два свойства в двух разных классах синхронизируются. Т.е. я использую Entity Framework, и эти свойства синхронизируются с базой данных.

public class UserGroup
{
    List<GroupMember> _Members;
    int _AcceptedMemberCount; // this is being synced to the database on save for performance reasons.

    public void Join(User user)
    {
        var member = GetOrCreateMember( user );
        member.State = MemberState.Accepted;
        UpdateAcceptedMemberCount();
    }

    public void Ban(User user)
    {
        var member = GetOrCreateMember( user );
        member.JoinState = MemberState.Banned;
        UpdateAcceptedMemberCount();
    }

    private GroupMember GetOrCreateMember(User user)
    {
       // Creates a GroupMember from User,
       // and add it to _Members if it doesn't exist.
    }

    private void UpdateAcceptedMemberCount()
    {
         _AcceptedMemberCount = _Members.Where(m => m.State == MemberState.Accepted).Count();
    }

}

public class GroupMember
{
    public MemberState State { get; internal set; }
}

Альтернативы, которые я знаю

Использование внутренних

Недостатком является то, что свойство все еще доступно для всех других классов в той же сборке. Т.е. у меня есть сборка с моими бизнес-моделями и сущностями. Создание отдельной сборки будет усложнять код, особенно когда вы используете Entity Framework, и нужно начать разделение объектов на несколько сборок.

Добавление SetState (UserGroup userGroup) в GroupMember

... что делает дополнительную ручную проверку, если UserGroup это заработало. Как и проверка того, был ли Пользователь добавлен как GroupMember в _Members. Чувствует себя действительно уродливым, и больше кода для поддержки, который может выйти из синхронизации и сломаться в будущем.

Использование вложенных классов (см. qaru.site/questions/34397/...)

  • На самом деле не работает с Entity Framework.
  • Делает код более подробным (всегда добавляя родительский класс в качестве префикса при работе с GroupMember).
  • GroupMember является важным автономным классом в этом приложении. Скрывать его за родительским классом, потому что это просто плохо.
  • Имеет ограниченное использование, потому что каждый класс может иметь только одну иерархию внешних классов.

Запишите его в сводке метода и проигнорируйте его

И просто надейтесь, что все прочтут это и никогда не начнут ругаться с состоянием GroupMember вручную. Недостатки этого, наверное, очевидны :)

Вопрос

Я не могу себе представить, что это действительно странный пример, и многие приложения должны иметь одинаковые проблемы. Какая здесь самая лучшая практика? Как это обычно решается?

Заранее спасибо,

  • 0
    Может быть, я просто пропустил это, но я не могу определить, какие свойства вы хотите синхронизировать.
  • 0
    Извините, может, я немного облажался с упрощением примера из реальной жизни. Я обновил пример.
Показать ещё 2 комментария
Теги:

1 ответ

0

Если для других классов может быть изменено значение GroupMember.State, вы можете использовать события, чтобы монитор UserGroup всякий раз, когда состояние менялось: когда State изменяется, оно вызывает событие, и класс UserGroup слушает его.

Если только пользователю UserGroup должно быть разрешено устанавливать состояние или если по какой-либо группе должно пройти какое-либо изменение состояния, то одна вещь, которую вы могли бы сделать, - это перемещать фактическое хранилище свойства State из GroupMember и в UserGroup:

public class UserGroup
{
    List<MemberState> _MemberStates;
    ...
}

Для этого потребуется, чтобы каждый GroupMember UserGroup принадлежащую ему UserGroup, поэтому это будет работать, только если каждый член группы является частью только одной группы пользователей. Если это так, то GroupMember будет выглядеть примерно так:

public class GroupMember
{
    private UserGroup _Parent;

    public GroupMember(UserGroup parent)
    {
        _Parent = parent;
    }

    public MemberState State { get {return _Parent.GetState(this);} }
    // Where GetState is a function that returns the state from _MemberState

    ...
}

Конечно, это создает сильную связь между ними (вместе они работают для обеспечения двух сторон одного и того же публичного интерфейса) и работает только в том случае, если каждый GroupMember всегда имеет ровно одну UserGroup.

Теперь, если каждый член группы может быть частью нескольких групп, то выше не будет работать, но угадывание из вашего примера здесь не так (потому что friend не решит это), поэтому я не буду вдаваться в возможные решения.

Подумав об этом, это действительно сводится к вашим точным требованиям и вариантам дизайна. Невозможно дать ответ на один размер, но, может быть, мне удалось вдохновить вас найти хороший выбор для вашего проекта.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню