2015-11-23 2 views
0

У меня есть два объекта: clsGroup и clsUser. Пользователи и группы - отдельные объекты.VBA Связывание двух объектов Двунаправлено

  • Каждый пользователь может находиться в любом количестве групп.
  • Каждая группа может содержать любое количество пользователей.

Вместо того, чтобы хранить список групп, принадлежащих каждому пользователю, и список пользователей, принадлежащих каждой группе в каждом объекте, предлагает VBA какой-либо способ связать их, чтобы из пользовательского объекта мы могли получить список групп, связанных с этим пользователем, и из объекта группы мы можем получить список пользователей, связанных с этой группой?

Я стараюсь избегать создания коллекций внутри пользователей и групп, поскольку синхронизация будет проблематичной.

ответ

1

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

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

Но что, если вам действительно нужна двунаправленная ассоциация ?

Существуют различные решения для решения круговых ссылок, используя различные методы. В VBA вам нужен механизм для выпуска перекрестных ссылок, в каком-то месте, когда вы знаете, что они больше не нужны. Другими словами, вам нужно как-то управлять себя время жизни ссылок.

Возможной возможностью было бы поддерживать глобальный словарь групп живых. Когда вы хотите удалить группу, скажем, в какой-то процедуре, существующей где-то в коде, вы сначала освобождаете (пустую) свою коллекцию студентов. Это нарушит циркулярную ссылку, позволяющую сборщику мусора работать правильно. Ниже приводится скелет такой возможной реализации.

'In class clsUser: 
    Public id as String '<~~ could be any type of identifier, such as Integer 
    Public groups as New Dictionary 
    Public Sub subscribeToGroup(g as clsGroup) 
     Me.groups.add g.id, g 
    End Sub 

    Public Sub unsubscribeFromGroup(g as clsGroup) 
     Me.groups.Remove g.id 
    End Sub 
'''''''''''''''''''''''''''''''''''''''''''''''' 

'In class clsGroup: 
    Public id as String '<~~ could be any type of identifier, such as Integer 
    Public users as New Dictionary 

    Public Sub registerUser(u as clsUser) 
     Me.users.add u.id, u 
    End Sub 

    Public Sub unregisterUser(u as clsUser) 
     Me.users.Remove u.id 
    End Sub 
    Public Sub removeAllUsers() 'empty the users collection, break the circular reference 
    For Each u In users: u.unsubscribeFromGroup(Me): Next 
    users.RemoveAll 
End Sub 
'''''''''''''''''''''''''''''''''''''''''''''''' 

У вас есть где-то (то есть глобальная переменная, или в каком-то классе под названием GroupManager и т.д.) Словарь групп и методы, чтобы создать или удалить группу.

Public AllGroups as Dictionary 
Function addGroup(id as String) as clsGroup 
    Set addGroup = new clsGroup 
    addGroup.id = id 
    AllGroups.Add id, addGroup 
End Function 

Sub removeGroup(g as clsGroup) 
    ' Explicitly Tell the group to free its users before going away. 
    ' This would not be needed if we didn't have circular references! 
    g.removeAllUsers 
    AllGroups.Remove g.id 
End Sub 

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

Смежные вопросы