【发布时间】:2019-07-09 10:25:36
【问题描述】:
我有以下课程,
用户:
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 循环中的 return 语句。如何重写这个?在这个例子中,我需要得到FirstName、LastName、BrandName、Name 和Email 的列表。但除了Email,我只得到前四个属性。
现在,上述问题已通过删除我在下面我自己的答案中发布的返回语句并遵循@Dialectus cmets 使用yield return 来解决。所以我罢工并更新了问题。
现在我遇到了另一个问题。如果一个类有多个[NestedSortable] 属性,则错误地分配了父类名称。
这个方法第一次被User类调用,比如var declaredTerms = GetTermsFromModel(typeof(User), null);
例子,
第一次调用后,parentsName 参数将为空,User 类中的[Sortable] 属性没有任何作用。
现在对于User 类中的[NestedSortable] Profile 属性,parentsName 将是Profile,因此Profile 类中的[Sortable] 属性将具有Name 作为Profile.BrandName 和以此类推。
Name最终列表中的属性如下,
预期输出:
名字、姓氏、Profile.BrandName、Profile.Client.Name、Profile.ProfileContact.Email
但实际输出:
名字、姓氏、Profile.BrandName、Profile.Client.Name、Profile.Client.ProfileContact.Email
请协助解决此问题。
谢谢,
阿卜杜勒
【问题讨论】:
-
sortTerms变量不应该是方法的输入参数。它实际上应该是方法的输出。此外,该方法返回IEnumerable,但任何地方都没有yield return。请参阅此以了解如何从递归函数yield return:stackoverflow.com/q/2055927/395718 -
@Dialectus 什么是产量以及为什么需要进行此更改?请帮忙
-
当需要学习新东西时,我更容易将您重定向到谷歌。搜索 c# yield return。这就是
IEnumerable的工作方式。 -
为什么不应该输入
sortTerms? -
应该是
foreach (var x in ...) yield return x;,而不是sortTerms.AddRange(...)。并且递归调用GetTermsFromModel也应该在循环中,foreach (var x in GetTermsFromModel(...)) yield return x;