记录转化为有层次结构的树状列表的通用算法

 

问题说明:
在获取数据库记录数据的时候, 通常返回的ArrayList集合, 没有了层次关系. 如果每次根据PID重新到数据库获取记录, 可以做到, 但有以下几个缺点:
1. 访问数据库记录次数随着记录的增多而增多
2. 由于需要多次访问数据库, 因此访问速度受影响
3. 需要数据库访问层的支持, 并对记录进行转化, 耦合性太强
4. 通用性不好, 每次需要一个新的类型列表, 就需要
解决方法:
我根据原有的树状结构算法代码, 编写一个通用的算法, 利用反射原理, 递归的对数据进行筛选.
这样只需要访问数据库一次, 然后就在内存中遍历, 而且适合于所有具有(PID, ID, Name)属性的实体类集合的排序.
 
如我需要生成设备类型实体类集合的树状结构时候, 代码如下:
ArrayList equipTypelist = equipmentType.GetAll();
    equipTypelist 
= CollectionHelper.GetTreeItems(equipTypelist);
    
this.ddlEquipmentTypes.DataSource = equipTypelist;
    
this.ddlEquipmentTypes.DataTextField = "Name";
    
this.ddlEquipmentTypes.DataValueField = "ID";
    
this.ddlEquipmentTypes.DataBind();

    
this.ddlEquipmentType.Items.Insert(0new ListItem("(全部)""0"));

    public class CollectionHelper
    
{            
        
private static ArrayList Fill(int pID, int level, ArrayList list)
        
{
            ArrayList returnList 
= new ArrayList();
            
foreach(object obj in list)
            
{
                
int typePID = (int)ReflectionUtil.GetProperty(obj, "PID");
                
int typeID = (int)ReflectionUtil.GetProperty(obj, "ID");
                
string typeName = ReflectionUtil.GetProperty(obj, "Name"as string;

                
if(pID == typePID)
                
{
                    
string newName = new string('-', level * 4+ typeName;
                    ReflectionUtil.SetProperty(obj, 
"Name", newName);
                    returnList.Add(obj);

                    returnList.AddRange(Fill(typeID, level
+1, list));
                }

            }

            
return returnList;
        }


        
/// <summary>
        
/// 生成有层次结构的列表
        
/// </summary>
        
/// <param name="list">具有Name,ID,PID成员的任何集合</param>
        
/// <returns></returns>

        public static ArrayList GetTreeItems(ArrayList list)
        
{
            
return Fill(-10, list);
        }
    
    }


    public sealed class ReflectionUtil
    
{
        
private ReflectionUtil()
        
{ }

        
public static BindingFlags bf = BindingFlags.DeclaredOnly | BindingFlags.Public |
            BindingFlags.NonPublic 
| BindingFlags.Instance | BindingFlags.Static;

        
public static void SetProperty(object obj, string name, object value)
        
{
            PropertyInfo fi 
= obj.GetType().GetProperty(name, bf);
            fi.SetValue(obj, value,
null);
        }


        
public static object GetProperty(object obj, string name)
        
{
            PropertyInfo fi 
= obj.GetType().GetProperty(name, bf);
            
return fi.GetValue(obj,null);
        }

}

效果图如下
树状列表效果图.jpg
posted @   ejiyuan  阅读(762)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述
点击右上角即可分享
微信分享提示