伪递归调用 = 堆栈溢出

本文关键字:堆栈 栈溢出 调用 递归 | 更新日期: 2023-09-27 18:21:04

我正在使用.NET Framework 4.5.1和C#开发 ASP.NET Web Api 2服务。

我正在按照这本书来做这件事:ASP.NET MVC 4和Web API从头到尾构建 REST 服务

我有这两节课。

用户

public class User
{
    public int UserId { get; set; }
    public string UserName { get; set; }
    public virtual ICollection<Group> Groups { get; set; }
}

public class Group
{
    public int GroupId { get; set; }
    public string GroupName { get; set; }
    public ICollection<User> Members { get; set; }
}

一个User可以有Group s,一个Group可以有User s作为Members

这两个类是我Data.Models,我使用Mapper类将它们"翻译"为Api.Models,使用以下两种方法:

public Models.User CreateUser(Data.Models.User modelUser)
{
    if (modelUser == null)
        return null;
    Models.User user = new Models.User()
    {
        UserId = modelUser.UserId,
        UserName = modelUser.UserName
    };
    if (modelUser.Groups != null)
        user.Groups = modelUser.Groups
            .Select(CreateGroup)
            .ToList();
}
public Models.Group CreateGroup(Data.Models.Group modelGroup)
{
    if (modelGroup == null)
        return null;
    Models.Group group = new Models.Group
    {
        GroupId = modelGroup.GroupId,
        GroupName = modelGroup.GroupName
    };
    if (modelGroup.Members != null)
        group.Members = modelGroup.Members
            .Select(CreateUser)
            .ToList();
    return group;
}

正如您在类Mapper中看到的,CreateUser方法调用CreateGroup方法,CreateGroup方法调用CreateUser

就我而言,user1group1的成员,group1 user1是成员。所以,我得到这个:

  • CreateUser user1时,它将呼叫CreateGroup进行group1
  • CreateGroup for group1 它将调用CreateUser进行user1
  • 等等...

关于如何避免这种无限递归调用的任何想法?

解决方案可能是从CreateUserCreateGroup方法中删除导航属性,如User上的Groups或类Members Group

伪递归调用 = 堆栈溢出

至少有两种可能的解决方案(我可以想到两种,但可以有更多(。

  1. (简单图形(将映射器方法拆分为两种 - 第一个用于初始化简单属性(名称、ID(,第二个用于初始化导航属性。然后,在代码中调用映射器的位置,编写一个稍长的脚本,该脚本使用这些新方法初始化从用户到组的导航属性,但不调用其他方法(从组到用户(,以便获得用户到组的图形。

  2. (完整图(向每个方法添加一个 tail 参数,该参数表示已访问的对象列表。然后,在递归调用时,检查该元素是否已在列表中,并且仅当它不在列表中时 - 添加它并递归调用。这样,递归调用将探索用户和组之间的整个依赖关系图,并确保没有用户和组被多次处理。