【发布时间】:2011-04-21 12:27:16
【问题描述】:
我正在尝试为对象创建一个属性列表。我可以很好地为基本对象创建一个列表,但是如果我遇到类型对象 A 包含对象 B 类型的属性的情况,该属性包含对象 A 类型的属性......好吧..然后我得到无限递归。
我所做的是向我的所有对象添加一个名为“RecursivePropertyList”的静态属性,它是每个具有递归的属性的List<string>。
所以,例如:
我有一个Person 类,其属性名为Vendor,类型为Vendor。
Vendor 类有一个名为 People 的属性,其类型为 List<Person>。
在Person 类中,我将RecursivePropertyList 的值设置为myList.Add("Vendor.People")。
在Vendor类中,我将RecursivePropertyList的值设置为myList.Add("People.Vendor")。
然后在创建属性列表的函数中,我检查当前的 objectname.propertyName 是否在 RecursivePropertyList 中,如果是,我不会将其添加到我的属性列表中,也不会向下钻取进入它以获取其属性。
这在上述情况下效果很好。
但是,当我遇到以下情况时,它开始失败:
具有List<ApplicationFunction_Application> 类型属性的Application 类。
具有List<ApplicationFunction_Application> 类型属性的ApplicationFunction 类。
一个ApplicationFunction_Application 类,它有两个属性,一个是Application 类型,另一个是ApplicationFunction 类型。
ApplicationFunction_Application 类的目的是定义Application 和ApplicationFunction 之间的多对多关系。
在Application 的RecursivePropertyList 中我放了:
myList.Add("ApplicationFunctions.Application");
在ApplicationFunction 的RecursivePropertyList 中我放了:
myList.Add("Applications.ApplicationFunction");
在ApplicationFunction_Application 的RecursivePropertyList 中我放了:
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;
}
关于我做错了什么有什么想法吗?
【问题讨论】:
-
为什么需要这个?我的第一直觉是,无论你想要实现什么,都必须有更好的方法,但由于我不知道你想要实现什么,所以我无法提出任何建议。
-
另外,你为什么不直接使用调试器呢?它可以准确地告诉您无限递归发生的位置,并让您逐步找出问题所在。
-
我需要这份清单,原因如下。我希望能够指定要实例化对象的哪些属性。我的对象的某些属性需要第二次访问数据库才能获取更多数据,有时我实际上并不需要这些数据。所以我希望能够设置不应该实例化的属性。为了做到这一点,我需要一个属性列表,其中包含一个 bool flg 值来确定该属性是否应该被“填充”。希望这有意义吗?如果有更好的方法来实现这一点,我会全力以赴。 =)
-
另外,我使用了调试器。在开始了几个小时并没有找到解决方案之后,我决定在这里发帖看看是否有人看到我明显遗漏的东西。
标签: c# class reflection recursion properties