代码之家  ›  专栏  ›  技术社区  ›  Amanda Kitson

函数创建属性树?

  •  0
  • Amanda Kitson  · 技术社区  · 16 年前

    我正在尝试创建对象的属性列表。我可以为基本对象创建一个列表,但是如果我有一个情况,类型对象a包含类型对象B的属性,而类型对象B包含类型对象a的属性。。。。好然后我得到无限递归。 我所做的是在我的所有对象中添加一个名为“RecursivePropertyList”的静态属性,它是一个 List<string> 每个具有递归的属性。

    例如: 我有一个 Person 使用名为 Vendor 类型 小贩 . 这个 小贩 类有一个名为 People 这是一种 List<Person> .

    在 人 I类设置 RecursivePropertyList 到 myList.Add("Vendor.People") . 在 小贩 类,我设置 递归属性列表 到 myList.Add("People.Vendor") .

    然后在创建属性列表的函数中,我检查当前的objectname是否正确。propertyName位于 递归属性列表 如果是这样的话,我不会把它添加到我的属性列表中,也不会深入到它中去获取它的属性。

    这在上述情况下非常有效。

    然而,当我遇到以下情况时,它开始失败: 一 Application 类,该类具有类型为的属性 List<ApplicationFunction_Application> . 一 ApplicationFunction 类,该类具有类型为的属性 列表<应用程序功能_应用程序> . 一 ApplicationFunction_Application 类,该类有两个属性,其中一个为 应用 ,和另一种类型 应用功能 . 会议的目的 ApplicationFunction\u应用程序 类定义了 应用 和 应用功能 .

    在 递归属性列表 属于 应用 我说:

    myList.Add("ApplicationFunctions.Application");

    在 递归属性列表 属于 应用功能 我说:

    myList.Add("Applications.ApplicationFunction");

    在 递归属性列表 属于 ApplicationFunction\u应用程序 我说:

    myList.Add("ApplicationFunction.Applications");

    myList.Add("Application.ApplicationFunctions");

    但是,我的剧本一直在循环,从未停止。

    以下是该函数使用的代码:

    首先,被调用的函数开始了整个过程:

    public static EquatableList<PropertyState> FillPropertyStateList(System.Type myObjectType, ref EquatableList<PropertyState> myPropertyStateList)
            {
                List<string> myRecursivePropertyList = FillDefaultRecursivePropertyList(myObjectType);
                return FillPropertyStateList(myObjectType, ref myPropertyStateList, string.Empty, string.Empty, myRecursivePropertyList);
            }
    

    然后是一个函数,它完成了大部分工作,并递归地调用自己来生成所有子对象的属性列表。

    public static EquatableList<PropertyState> FillPropertyStateList(System.Type myObjectType, ref EquatableList<PropertyState> myPropertyStateList, string myParentPrefix, string myObjectName, List<string> myRecursivePropertyList)
            {
                if (myPropertyStateList == null)
                {
                    myPropertyStateList = new EquatableList<PropertyState>();
                }
                if (string.IsNullOrEmpty(myParentPrefix))
                {
                    myParentPrefix = string.Empty;
                }
                else if (!myParentPrefix.EndsWith("."))
                {
                    myParentPrefix = myParentPrefix + ".";
                }
                if (string.IsNullOrEmpty(myObjectName))
                {
                    myObjectName = string.Empty;
                }
                else
                {
                    myObjectName = myObjectName + ".";
                }
    
                foreach (System.Reflection.PropertyInfo info in myObjectType.GetProperties())
                {
                    if (info.PropertyType.BaseType == typeof(BOBase))
                    {
                        if (!myRecursivePropertyList.Exists(delegate(string x) { return x.Equals(myObjectName + info.Name); }))
                        {
                            myPropertyStateList.Add(new PropertyState(myParentPrefix + myObjectName + info.Name, true, PropertyType.BOBase));
                            List<string> myChildRecursivePropertyList = FillDefaultRecursivePropertyList(info.PropertyType);
                            myChildRecursivePropertyList.AddRange(myRecursivePropertyList.FindAll(delegate(string x) { return Regex.IsMatch(x, info.Name + ".*"); }));
                            FillPropertyStateList(info.PropertyType, ref myPropertyStateList, myParentPrefix + myObjectName, info.Name, myChildRecursivePropertyList);
                        }
                    }
                    else if (info.PropertyType.IsGenericType
                        && (info.PropertyType.BaseType.GetGenericTypeDefinition() == typeof(List<>) || info.PropertyType.BaseType.GetGenericTypeDefinition() == typeof(Library.EquatableList<>)))
                    {
                        if (!myRecursivePropertyList.Exists(delegate(string x) { return x.Equals(myObjectName + info.Name); }))
                        {
                            myPropertyStateList.Add(new PropertyState(myParentPrefix + myObjectName + info.Name, true, PropertyType.BOBaseCollection));
                            List<string> myChildRecursivePropertyList = FillDefaultRecursivePropertyList(info.PropertyType.BaseType.GetGenericArguments()[0]);
                            myChildRecursivePropertyList.AddRange(myRecursivePropertyList.FindAll(delegate(string x) { return Regex.IsMatch(x, info.Name + ".*"); }));
                            FillPropertyStateList(info.PropertyType.BaseType.GetGenericArguments()[0], ref myPropertyStateList, myParentPrefix + myObjectName, info.Name, myChildRecursivePropertyList);
                        }
                    }
                    else
                    {
                        myPropertyStateList.Add(new PropertyState(myParentPrefix + myObjectName + info.Name, true, PropertyType.Standard));
                    }
    
                }
                return myPropertyStateList;
            }
    

    获取默认递归属性列表的helper函数:

    private static List<string> FillDefaultRecursivePropertyList(System.Type myObjectType)
        {
            List<string> myRecursivePropertyList = new List<string>();
            if (myObjectType.BaseType == typeof(BOBase))
            {
                System.Reflection.PropertyInfo pi = myObjectType.GetProperty("RecursivePropertyList", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
                if (pi != null)
                {
                    myRecursivePropertyList = (List<string>)pi.GetValue(null, null);
                }
            }
            return myRecursivePropertyList;
        }
    

    你知道我做错了什么吗?

    1 回复  |  直到 16 年前
        1
  •  0
  •   Timwi    16 年前

    我还没有深入研究代码,但是您是否考虑过使用属性来表示哪些属性是递归的?这可能会让你省去维护单独的静态属性列表的麻烦。列表方法似乎容易出现潜在的困难同步问题。

    ETA:示例代码:

    如果我理解正确的话,像这样的东西可能适用于属性级属性。它包括一个helper方法,用于从给定类型检索标记为递归的属性,这可能有助于构建树。

    [AttributeUsage(AttributeTargets.Property)]
    public class RecursivePropertyAttribute
        : Attribute
    {
        private static Dictionary<Type, List<PropertyInfo>> _Cache = new Dictionary<Type, List<PropertyInfo>>();
    
        public IEnumerable<PropertyInfo> GetRecursiveProperties(Type t)
        {
            // Check the cache for the type
            if (!_Cache.ContainsKey(t))
            { 
                // Create the entry
                _Cache.Add(t, new List<PropertyInfo>());
    
                // Add properties that have the attribute
                foreach (PropertyInfo p in t.GetProperties())
                {
                    if (p.IsDefined(typeof(RecursivePropertyAttribute), true))
                        _Cache[t].Add(p);
                }
            }
    
            return _Cache[t];
        }
    }