创建属性树的函数?

发布于 2024-09-26 09:27:51 字数 6389 浏览 2 评论 0原文

我正在尝试创建对象的属性列表。我可以为基本对象创建一个列表,但是如果我遇到这样的情况,类型对象 A 包含类型对象 B 的属性,而类型对象 B 又包含类型对象 A 的属性.... 好吧.. 那么我会得到无限递归。 我所做的就是向我的所有对象添加一个名为“RecursivePropertyList”的静态属性,它是每个具有递归属性的 List

因此,例如: 我有一个 Person 类,其属性名为 Vendor,类型为 VendorVendor 类有一个名为 People 的属性,其类型为 List

Person 类中,我将 RecursivePropertyList 的值设置为 myList.Add("Vendor.People")。 在 Vendor 类中,我将 RecursivePropertyList 的值设置为 myList.Add("People.Vendor")

然后在创建属性列表的函数中,我检查当前的 objectname.propertyName 是否在 RecursivePropertyList 中,如果是,我不会将其添加到我的属性列表中,也不会将其添加到属性列表中。深入研究它以获取其属性。

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

但是,当我遇到以下情况时,它开始失败: 具有 List 类型属性的 Application 类。 具有 List 类型属性的 ApplicationFunction 类。 一个 ApplicationFunction_Application 类,具有两个属性,一个为 Application 类型,另一个为 ApplicationFunction 类型。 ApplicationFunction_Application 类的用途是定义 ApplicationApplicationFunction 之间的多对多关系。

ApplicationRecursivePropertyList 中,我放置:

myList.Add("ApplicationFunctions.Application");

RecursivePropertyListApplicationFunction 我把:

myList.Add("Applications.ApplicationFunction");

ApplicationFunction_ApplicationRecursivePropertyList 中我put:

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;
        }

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

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;
    }

对我做错了什么有什么想法吗?

I am trying to create a List of properties for objects. I can create a list for basic objects just fine, but if I have a situation where type object A contains a property of type object B which contains a property of type object A.... well.. then I get infinite recursion.
What I've done is added a static property to all of my objects called "RecursivePropertyList" which is a List<string> of each property that has recursion.

So, for example:
I have a Person class with a property called Vendor of type Vendor.
The Vendor class has a property called People which is of type List<Person>.

In the Person class I set the value of RecursivePropertyList to myList.Add("Vendor.People").
In the Vendor class, I set the value of RecursivePropertyList to myList.Add("People.Vendor").

Then in my function that creates the property list, I check to see if the current objectname.propertyName is in the RecursivePropertyList and if so, I don't add it to my list of properties and don't drill down into it to get its properties.

This works great in the situation described above.

However, it begins to fail when I have the following situation:
An Application class that has a property of type List<ApplicationFunction_Application>.
An ApplicationFunction class that has a property of type List<ApplicationFunction_Application>.
An ApplicationFunction_Application class that has two properties, one of type Application, and another of type ApplicationFunction.
The purpose of the ApplicationFunction_Application class is to define a many-to-many relationship between Application and ApplicationFunction.

In the RecursivePropertyList of Application I put:

myList.Add("ApplicationFunctions.Application");

In the RecursivePropertyList of ApplicationFunction I put:

myList.Add("Applications.ApplicationFunction");

In the RecursivePropertyList of ApplicationFunction_Application I put:

myList.Add("ApplicationFunction.Applications");

myList.Add("Application.ApplicationFunctions");

But, my script just keeps looping forever and never stops.

Here is the code used by the function:

First, the function that is called that begins the whole thing:

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);
        }

Then the function that does the meat of the work and that calls itself recursively to generate the property list for all child objects.

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;
        }

The helper function that gets the default recursive properties list:

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;
    }

Any ideas on what I'm doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

深居我梦 2024-10-03 09:27:51

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

ETA:示例代码:

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

[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];
    }
}

I haven't dug into the code, yet, but have you considered using an Attribute to denote which properties are recursive? That might save you the headache of having to maintain the separate static list of properties. It seems like the list approach could be prone to potentially difficult synchrnonization issues.

ETA: Sample code:

If I'm understanding this correctly, something like this would probbaly work for a property-level attribute. It includes a helper method to retrieve the properties marked as Recursive from the given type, which might help when building the tree.

[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];
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文