递归函数无法在c#

时间:2019-07-09 10:25:36

标签: c# recursion

我有以下课程,

用户:

public class User:Domain
    {
        [Sortable]
        public string FirstName { get; set; }

        [Sortable]
        public string LastName { get; set; }

        [NestedSortable]
        public Profile Profile { get; set; }
    }

个人资料:

public class Profile : Domain
    {
        [Sortable]
        public string BrandName { get; set; }

        [NestedSortable]
        public Client Client { get; set; }

        [NestedSortable]
        public ProfileContact ProfileContact { get; set; }
    }

客户

public class Client : Domain
    {
        [Sortable]
        public string Name { get; set; }
    }

个人资料联系人:

public class ProfileContact : Domain
    {
        [Sortable]
        public string Email { get; set; }
    }

我正在编写一个递归函数,以获取所有用[Sortable]装饰的属性。当我只有一个[NestedSortableProperty]时,此方法效果很好,但当我有多个private static IEnumerable<SortTerm> GetTermsFromModel( Type parentSortClass, List<SortTerm> sortTerms, string parentsName = null, bool hasNavigation = false) { if (sortTerms is null) { sortTerms = new List<SortTerm>(); } sortTerms.AddRange(parentSortClass.GetTypeInfo() .DeclaredProperties .Where(p => p.GetCustomAttributes<SortableAttribute>().Any()) .Select(p => new SortTerm { ParentName = parentSortClass.Name, Name = hasNavigation ? $"{parentsName}.{p.Name}" : p.Name, EntityName = p.GetCustomAttribute<SortableAttribute>().EntityProperty, Default = p.GetCustomAttribute<SortableAttribute>().Default, HasNavigation = hasNavigation })); var complexSortProperties = parentSortClass.GetTypeInfo() .DeclaredProperties .Where(p => p.GetCustomAttributes<NestedSortableAttribute>().Any()); if (complexSortProperties.Any()) { foreach (var parentProperty in complexSortProperties) { var parentType = parentProperty.PropertyType; if (string.IsNullOrWhiteSpace(parentsName)) { parentsName = parentType.Name; } else { parentsName += $".{parentType.Name}"; } return GetTermsFromModel(parentType, sortTerms, parentsName, true); } } return sortTerms; } 时,效果不佳。

这是我的递归函数:

foreach

发生这种情况是由于FirstName循环内的return语句。如何重写呢?在此示例中,我需要获取LastNameBrandNameNameEmailEmail的列表。但是我只得到除yield return之外的前四个属性。

现在,通过删除下面我自己的答案中所发布的return语句并遵循@Dialecticus注释来使用[NestedSortable],可以解决上述问题。所以我点击并更新了问题。

现在我遇到了另一个问题。如果一个类具有多个User属性,则会错误地分配父类名称。

第一次使用var declaredTerms = GetTermsFromModel(typeof(User), null);类的parentsName类调用此方法

示例

在第一次调用后,[Sortable]参数将为null,并且User类中的[NestedSortable]属性无效。

现在,对于Profile类中的User parentsName属性,Profile将是[Sortable],因此{{ 1}}类将Profile设为Name,依此类推。

最终列表中的

Profile.BrandName属性如下,

预期输出:

名字,姓氏,Profile.BrandName,Profile.Client.Name,Profile.ProfileContact.Email

但实际输出:

名字,姓氏,Profile.BrandName,Profile.Client.Name,Profile.Client.ProfileContact.Email

请协助解决此问题。

谢谢

阿卜杜勒

1 个答案:

答案 0 :(得分:0)

经过一些调试后,我在foreach循环中删除了return语句,并修复了第一个问题。

更改自

return GetTermsFromModel(parentType, sortTerms, parentsName, true);

GetTermsFromModel(parentType, sortTerms, parentsName, true);

然后按照@Dialecticus注释删除,将sortTerms作为输入参数,并删除代码中的参数,并将sortTerms.AddRange(...)更改为yield return

更改自

sortTerms.AddRange(parentSortClass.GetTypeInfo()
                       .DeclaredProperties
                       .Where(p => p.GetCustomAttributes<SortableAttribute>().Any())
                       .Select(p => new SortTerm
                       {
                           ParentName = parentSortClass.Name,
                           Name = hasNavigation ? $"{parentsName}.{p.Name}" : p.Name,
                           EntityName = p.GetCustomAttribute<SortableAttribute>().EntityProperty,
                           Default = p.GetCustomAttribute<SortableAttribute>().Default,
                           HasNavigation = hasNavigation
                       }));

foreach (var p in properties)
            {
                yield return new SortTerm
                {
                    ParentName = parentSortClass.Name,
                    Name = hasNavigation ? $"{parentsName}.{p.Name}" : p.Name,
                    EntityName = p.GetCustomAttribute<SortableAttribute>().EntityProperty,
                    Default = p.GetCustomAttribute<SortableAttribute>().Default,
                    HasNavigation = hasNavigation
                };
            }

对于复杂属性,也从更改为

GetTermsFromModel(parentType, sortTerms, parentsName, true);

var complexProperties = GetTermsFromModel(parentType, parentsName, true);

                    foreach (var complexProperty in complexProperties)
                    {
                        yield return complexProperty;
                    }

对于最后一个问题,我遇到了这个名称,在内部foreach循环修复它之后,添加以下代码,

parentsName = parentsName.Replace($".{parentType.Name}", string.Empty);

这是完整的更新后的工作代码:

private static IEnumerable<SortTerm> GetTermsFromModel(
            Type parentSortClass,
            string parentsName = null,
            bool hasNavigation = false)
        {
            var properties = parentSortClass.GetTypeInfo()
                       .DeclaredProperties
                       .Where(p => p.GetCustomAttributes<SortableAttribute>().Any());

            foreach (var p in properties)
            {
                yield return new SortTerm
                {
                    ParentName = parentSortClass.Name,
                    Name = hasNavigation ? $"{parentsName}.{p.Name}" : p.Name,
                    EntityName = p.GetCustomAttribute<SortableAttribute>().EntityProperty,
                    Default = p.GetCustomAttribute<SortableAttribute>().Default,
                    HasNavigation = hasNavigation
                };
            }

            var complexSortProperties = parentSortClass.GetTypeInfo()
                       .DeclaredProperties
                       .Where(p => p.GetCustomAttributes<NestedSortableAttribute>().Any());

            if (complexSortProperties.Any())
            {
                foreach (var parentProperty in complexSortProperties)
                {
                    var parentType = parentProperty.PropertyType;

                    //if (string.IsNullOrWhiteSpace(parentsName))
                    //{
                    //    parentsName = parentType.Name;
                    //}
                    //else
                    //{
                    //    parentsName += $".{parentType.Name}";
                    //}

                    var complexProperties = GetTermsFromModel(parentType, string.IsNullOrWhiteSpace(parentsName) ? parentType.Name : $"{parentsName}.{parentType.Name}", true);

                    foreach (var complexProperty in complexProperties)
                    {
                        yield return complexProperty;
                    }

                    //parentsName = parentsName.Replace($".{parentType.Name}", string.Empty);
                }
            }
        }