Параметры:
- внедрить тест на членство, например, проверьте bar-is-member-of-foo перед добавлением
- перенести отношение «многие ко многим» в свой класс
последнее предпочтительнее, я думаю - оно более реляционно
конечно, с примером foo-bar мы действительно не знаем, какова цель, поэтому ваш пробег может варьироваться
РЕДАКТИРОВАТЬ: учитывая код в исходном вопросе, # 1 не будет работать, потому что бесконечная рекурсия происходит до того, как что-либо будет добавлено в любой список.
Есть несколько проблем с этим подходом / вопросом, возможно потому, что он был абстрагирован почти до глупости - хорошо для иллюстрации проблемы кодирования, не так хорошо для объяснения первоначального намерения / цели:
- классы-обертки на самом деле ничего не переносят и не добавляют никакого полезного поведения; из-за этого трудно понять, зачем они нужны
- с данной структурой, вы не можете инициализировать списки в конструкторе вообще , потому что каждый список оболочек сразу создает новый экземпляр другого списка оболочек
- даже если вы отделяете инициализацию от конструкции, у вас все еще есть циклическая зависимость со скрытым членством (т.е. обертки ссылаются друг на друга, но скрывают элементы foo / bar от проверки содержимого; это не имеет значения, потому что код никогда не получает все равно добавить что-нибудь в любой список!)
- прямой реляционный подход будет работать, но требует механизмов поиска и предполагает, что обертки будут создаваться по мере необходимости, а не заранее, например. массив с функциями поиска или пара словарей (например, Dictionary>, Dictionary>) будут работать для отображения, но могут не соответствовать вашей объектной модели
Заключение
Я не думаю, что структура , как описано , будет работать. Не с DI, не с фабрикой, совсем нет - потому что оболочки ссылаются друг на друга, скрывая подсписки.
Эта структура намекает на необоснованные неверные предположения, но без контекста мы не можем понять, какими они могут быть.
Пожалуйста, переформулируйте проблему в исходном контексте с объектами реального мира и желаемой целью / намерением.
Или, по крайней мере, укажите, какую структуру, по вашему мнению, должен генерировать ваш пример кода . ; -)
Добавление
Спасибо за разъяснения, это делает ситуацию более понятной.
Я не работал с привязкой данных WPF - но я просмотрел эту статью MSDN - поэтому следующее может быть, а может и не быть полезным и / или правильным:
- Я думаю, что коллекции категорий и рецептов в классах модели представления являются избыточными
- у вас уже есть информация M: M в базовом объекте категории, так зачем дублировать ее в модели представления
- похоже, что обработчики, измененные коллекцией, также вызовут бесконечную рекурсию
- обработчики, изменяющие коллекцию, по-видимому, не обновляют базовую информацию M: M для упакованного рецепта / категории
- Я думаю, что цель модели представления состоит в том, чтобы представить базовые данные модели, а не индивидуально оборачивать каждый из ее компонентов.
- Это кажется избыточным и нарушением инкапсуляции
- Это также источник вашей проблемы бесконечной рекурсии
- Наивно, я бы ожидал, что свойства ObservableCollection просто вернут коллекции базовой модели ...
Структура, которую вы имеете, представляет собой представление «инвертированный индекс» отношения «многие ко многим», что довольно часто встречается в оптимизированных поисках и управлении зависимостями. Это сводится к паре отношений один-ко-многим. Посмотрите на пример GamesViewModel в статье MSDN - обратите внимание, что свойство Games имеет значение
ObservableCollection<Game>
а не
ObservableCollection<GameWrapper>