构建两个对象之间的导航路径 [英] Constructing a navigation path between two objects

查看:123
本文介绍了构建两个对象之间的导航路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定两个.NET对象(根和叶)中的任意一个对象图(由属性和集合链接),是否有一个现有的API或例子来构建一个路径(就像一个WPF属性绑定路径,或XML XPath的),从一个到另一个弄? 源(即它要找出路径的对象),将是叶对象。

Given two .NET objects (a root and a leaf) in an arbitrary object graph (linked by properties and collections), is there an existing API or example to construct a path (something like a WPF property binding path, or XML XPath) to get from one to the other? The "source" (ie. the object which wants to find out the path), will be the leaf object.

索引的位置也必须支持。 (例如: Foo.Bar [42] .Baz [青蛙。QUUX )。

Indexed locations must also be supported. (eg. Foo.Bar[42].Baz["frog"].Quux).

这是主要用于错误报告 - 我想,让对象记录显示错误,他们是在对象模型,而不仅仅是他们的类型名称。 (这是重要的,因为同一类型的对象可能包含由大量的其他对象类型的,并以固定的任何问题将根据该位置而变化所需要的用户动作。)

This is mainly intended for error reporting -- I would like to let objects log an error showing where they are in the object model, rather than just by their type name. (This is important because the same type of object might be contained by a large number of other object types, and the user action required to fix any issues will vary depending on that location.)

我可以用手辊一些东西,通过为每个对象的引用,其​​母公司和递归要求每位家长如何让孩子的伎俩。但在此之前我去这样做,我想知道是否有任何现有的/更好的解决方案。 (这是脆弱,如果有人忘记更新父链接,或者如果一个目的也可以通过两个不同的路径到达,尽管这应该是罕见的。)

I can hand-roll something which does the trick by giving each object a reference to its parent and recursively asking each parent how to get to the child. But before I go do that I was wondering if there were any existing/better solutions. (And this is fragile if someone forgets to update the parent link, or if one object can be reached by two different paths, although that should be rare.)

推荐答案

这是如何你可以开始一些非常简化字,希望这将有助于...

This is some very simplified variant of how you can start, hope this will help...

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace ConsoleApplication2
{
    class Test2
    {
        public bool BoolProp { get; set; }

        public int[] ArrayProp { get; set; }
    }

    class Test1
    {
        public string StringProp { get; set; }

        public Dictionary<string, Test2> DictionaryProp { get; set; }
    }

    class Program
    {


        private static string ObjToPathKey(object key)
        {
            if (key == null) return "null";
            if (key is string) return string.Format("\"{0}\"", key);
            return key.ToString();
        }

        public static IEnumerable<KeyValuePair<string, object>> GetFullTree(object root, string currentPath)
        {
            if (root == null) yield break;

            yield return new KeyValuePair<string, object>(currentPath, root);

            var type = root.GetType();
            if (!type.IsClass || type == typeof(string)) yield break;

            if (root is IEnumerable)
            {
                if (root is IDictionary)
                {
                    IDictionary d = (IDictionary) root;
                    foreach (var key in d.Keys)
                    {
                        var child = d[key];
                        foreach (var subchildPair in GetFullTree(child, string.Format("{0}[{1}]", currentPath, ObjToPathKey(key))))
                        {
                            yield return subchildPair;
                        }
                    }
                    yield break;
                }

                int i = 0;
                if (root is IList)
                {
                    foreach (var child in (IEnumerable)root)
                    {
                        foreach (var subChildPair in GetFullTree(child, string.Format("{0}[{1}]", currentPath, i)))
                        {
                            yield return subChildPair;
                        }
                        ++i;
                    }
                    yield break;
                }

                throw new NotSupportedException();
            }

            if (type.IsClass)
            {
                foreach (PropertyInfo propertyInfo in type.GetProperties())
                {
                    //TODO: Add indexers support
                    object propertyValue = propertyInfo.GetValue(root, null);
                    foreach (var subChildPair in GetFullTree(propertyValue, string.Format("{0}.{1}", currentPath, propertyInfo.Name)))
                    {
                        yield return subChildPair;
                    }
                }
            }
        }

        static void Main(string[] args)
        {
            Test1 t = new Test1()
                          {
                              StringProp = "Some value",
                              DictionaryProp = new Dictionary<string, Test2>()
                                                   {
                                                       {
                                                           "key1", new Test2()
                                                                       {
                                                                           ArrayProp = new[] {1, 2, 3},
                                                                           BoolProp = true
                                                                       }
                                                           },
                                                       {
                                                           "key 2", new Test2()
                                                                        {
                                                                            ArrayProp = new[] {4, 5, 6, 7},
                                                                            BoolProp = false
                                                                        }
                                                           }
                                                   }
                          };

            foreach (var pair in GetFullTree(t, "t"))
            {
                Console.WriteLine("{0} = {1}", pair.Key, pair.Value);
            }

            Console.Read();

            /* Program output:
                t = ConsoleApplication2.Test1
                t.StringProp = Some value
                t.DictionaryProp = System.Collections.Generic.Dictionary`2[System.String,Console
                Application2.Test2]
                t.DictionaryProp["key1"] = ConsoleApplication2.Test2
                t.DictionaryProp["key1"].BoolProp = True
                t.DictionaryProp["key1"].ArrayProp = System.Int32[]
                t.DictionaryProp["key1"].ArrayProp[0] = 1
                t.DictionaryProp["key1"].ArrayProp[1] = 2
                t.DictionaryProp["key1"].ArrayProp[2] = 3
                t.DictionaryProp["key 2"] = ConsoleApplication2.Test2
                t.DictionaryProp["key 2"].BoolProp = False
                t.DictionaryProp["key 2"].ArrayProp = System.Int32[]
                t.DictionaryProp["key 2"].ArrayProp[0] = 4
                t.DictionaryProp["key 2"].ArrayProp[1] = 5
                t.DictionaryProp["key 2"].ArrayProp[2] = 6
                t.DictionaryProp["key 2"].ArrayProp[3] = 7
             */
        }
    }
}

这篇关于构建两个对象之间的导航路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆