使用递归属性 ASP.NET / C#

Posted

技术标签:

【中文标题】使用递归属性 ASP.NET / C#【英文标题】:Using recursive properties ASP.NET / C# 【发布时间】:2014-05-05 04:03:04 【问题描述】:

我正在寻找一种方法来获取通用结果集并将其转换为使用 jQuery Dyantree 的 ASP.NET MVC 的树结构。我有一个像这样的测试类:

public class GenericResults

    public string ClaimId  get; set; 
    public string DrugName  get; set; 
    public int PatientId  get; set; 

    //simulates database call, this could be any type of result set
    public static List<GenericResults> MockDatabaseCall()
    
        return new List<GenericResults>()
        
            new GenericResults  ClaimId = "abc", DrugName="Drug 1",  PatientId=1 ,
            new GenericResults  ClaimId = "bcd", DrugName="Drug 2",  PatientId=1 ,
            new GenericResults  ClaimId = "def", DrugName="Drug 3",  PatientId=1 ,
            new GenericResults  ClaimId = "fgi", DrugName="Drug 4",  PatientId=1 ,
            new GenericResults  ClaimId = "ijk", DrugName="Drug 5",  PatientId=2 ,
            new GenericResults  ClaimId = "klm", DrugName="Drug 6",  PatientId=2 ,
            new GenericResults  ClaimId = "mno", DrugName="Drug 7",  PatientId=2 ,
            new GenericResults  ClaimId = "pqr", DrugName="Drug 8",  PatientId=2 ,
            new GenericResults  ClaimId = "qrs", DrugName="Drug 9",  PatientId=2 ,
            new GenericResults  ClaimId = "stu", DrugName="Drug 10", PatientId=2 ,
        ;
    

Dynatree 需要的数据结构如下:

public string Title  get; set; 
public List<TreeView> Children  get; set; 
public bool IsFolder

    get
    
        return this.Children.Count > 0;
    

在这个例子中,我们真的不需要ClaimId 属性,但是我想重用我已经编写的存储过程来提供给树,所以我想包含它。我需要已经分组的内容成为它自己的TreeView 对象,并且Children 属性是所有具有分组内容值的记录。到目前为止,MockDatabaseCallMethod,如果我对PatientId 进行分组,我将需要两个TreeView 对象:一个用于每个唯一的 PatientId。我希望能够递归地执行此操作,但不确定如何,因为有些项目将是叶子(没有孩子),这很好。这是我的尝试:

public class TreeView

    public string Title
    
        get;
        set;
    

    public List<TreeView> Children  get; set; 

    public bool IsFolder
    
        get
        
            return this.Children.Count > 0;
        
    

    //made void for the time being to limit compilation errors
    public static void ListToTree(string displayName,string groupedOn)
    
        //seed data
        List<GenericResults> results = GenericResults.MockDatabaseCall();

        //"group" on the property passed by the user
        var query = results.Select(x => x.GetType().GetProperty(groupedOn).GetValue(x,null)).Distinct();

        foreach (var i in query)
        
            var treeView = new TreeView();
            treeView.Title = displayName;

            //iterate over results, if object has the property value of what's currently being iterated over
            //create a new TreeView object for it
            treeView.Children = results.Where(x => x.GetType().GetProperty(groupedOn).GetValue(x, null) == i)
                                       .Select(n => new TreeView
                                                    
                                                        Title = displayName,
                                                        Children = x <--no idea what to do here
                                                    );
        
    

理想情况下,我想要一个 ToTree 扩展方法,但首先我想获得一些关于此的指针。谢谢:)

【问题讨论】:

听起来你的TreeView 永远不会有超过两个级别 - 一个级别用于组值,下一个级别用于所有具有“当前”值的项目?如果是这样,递归方法是矫枉过正的。只需使用简单的results.GroupBy(...) 或类似的方式将项目分组。 【参考方案1】:

我不确定我是否理解正确,但如果我理解了,我会建议以下解决方案:

-) 在TreeView 中将属性public List&lt;TreeView&gt; Children get; set; 更改为public IEnumerable&lt;GenericResults&gt; Children get; set;

-) 将您的 void ListToTree(string displayName 方法替换为以下方法:

public static List<TreeView> ListToTree(string displayName, string groupedOn)

    //seed data
    List<GenericResults> results = GenericResults.MockDatabaseCall();

    List<TreeView> trees = new List<TreeView>();

    //"group" on the property passed by the user
    var query = results.Select(x => x.GetType().GetProperty(groupedOn).GetValue(x, null)).Distinct();

    foreach (int i in query)
    
        var treeView = new TreeView();
        treeView.Title = displayName;
        treeView.Children = results.Where(x => ((int)x.GetType().GetProperty(groupedOn).GetValue(x, null)) == i);

        trees.Add(treeView);
    

    return trees;

但我不确定我是否理解正确;-)

【讨论】:

嗨,马库斯。我尝试了您的代码,但在 results.Where... 行出现错误 can't convert IEnumerable to List. 是的,因为您还需要更改属性(请参阅上文开头的文字)

以上是关于使用递归属性 ASP.NET / C#的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NE网站发布注意事项

ASP.NET 核心标识。使用 ApplicationDbContext 和 UserManager。他们是不是共享上下文?

在 WPF、Silverlight 和 ASP.NET 之间共享一个公共 DAL

ASP.NET Web API 身份验证(Web + 移动)

缩放 ASP.NET 应用程序

理解ASP.NET Core