Поиск объекта графа - PullRequest
       1

Поиск объекта графа

2 голосов
/ 28 января 2012

Я думал, что смогу сделать это намного проще, чем кажется.

Мне нужен наиболее эффективный способ, позволяющий получить все экземпляры определенного типа в графе объектов.

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

Почему я хочу это сделать? У меня есть тип, из которого получены другие. Этот тип имеет общие свойства и, что более важно, конкретный тип, идентифицирующий ошибки, HasErrors. Этот тип используется при построении моделей. Каждая модель отличается. Некоторые простые и мелкие, некоторые сложные и глубокие. Как правило, каждый сложный узел будет коллекцией или пользовательским типом, производным от этого типа. Мне нужен быстрый способ обойти любой их экземпляр, проверяя все свойства HasErrors. Любой экземпляр true указывает на ошибку модели.

Model  
    CustomerId (int)  
    CustomerDetails : MyType  
        Name (string)  
        DoB (DateTime)  
        Addresses (Collection<Address : MyType>)  
            [Line1 (string)  
             Line2 (string)]  

Надеюсь, этот вид иллюстрирует.

Ответы [ 2 ]

0 голосов
/ 31 января 2012

Это что-то вроде «нестандартного мышления», но я не думаю, что вы должны искать вниз дерево, я думаю, что вы должны распространять ошибки вверх дерево.

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

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

0 голосов
/ 29 января 2012

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

interface IComponent
{
    IEnumerable<IComponent> Components { get; }
}

, а затем использовать этот интерфейс для обхода всего графа объектов.Если в графе могут содержаться циклы, вы должны принять меры против этого, используя что-то вроде HashSet<IComponent> посещенных вершин.

При реализации этого интерфейса могут быть полезны блоки итераторов:

class FamilyMember : IComponent
{
    IEnumerable<IComponent> IComponent.Components
    {
        get
        {
            if (Father != null)
                yield return Father;

            if (Mother != null)
                yield return Mother;

            foreach (var child in Children)
                yield return child;
        }
    }
}

Если у вас уже есть много типов, которые являются частью графа объектов, это может быть утомительно.Если это так, и вы не возражаете против снижения производительности, лучше использовать рефлексию.

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