完全合格的财产名称

我正在尝试阻止System.NullReferenceException。

我有一个公司,有一个雇员集合。 每个员工都有一系列技能。

SelectedEmployee指向Employee集合中当前选定的元素。

SelectedSkill指向技能集合中当前选定的元素。

我有一个ListView,其ItemSource绑定到Skills集合; ListView的SelectedItem绑定到SelectedSkill。

删除技能时,我希望ListView滚动到最后一个元素。

private void DeleteSelectedSkillFromSelectedEmployee() { Company.SelectedEmployee.Skills.Remove(Company.SelectedEmployee.SelectedSkill); EmployeeSkillsListView.ScrollIntoView(Company.SelectedEmployee.Skills.Last()); } 

如果尚未选择Employee,则SelectedEmployee将为null。 在方法内部执行任何操作时,这将导致System.NullReferenceException。

注意:我使用了一个扩展方法来替换.Last(),因此它不会在空集合上出错。

为了解决这个问题,我使用了Util方法:

 public static class Utils { public static bool PropertyExists(Object obj, String name) { foreach (String part in name.Split('.')) { if (obj == null) { return false; } Type type = obj.GetType(); System.Reflection.PropertyInfo info = type.GetProperty(part); if (info == null) { return false; } obj = info.GetValue(obj, null); } return obj != null; } } 

所以它现在看起来像这样:

 private void DeleteSelectedSkillFromSelectedEmployee() { if(Utils.PropertyExists(Company, "SelectedEmployee.SelectedSkill")) { Company.SelectedEmployee.Skills.Remove(Company.SelectedEmployee.SelectedSkill); EmployeeSkillsListView.ScrollIntoView(Company.SelectedEmployee.Skills.Last()); } } 

上面的一切都很好。 这不是确切的场景或代码,所以不要担心纠正上面的任何事情(只是假设它工作正常)。 这只是下面的问题,我真的很想知道。

(想象一下,SelectedEmployee和SelectedSkill不为null)

有没有办法获得财产的完全限定名称? 所以我可以这样做:

 if(Utils.PropertyExists(Company, GetFullyQualifiedName(Company.SelectedEmployee.SelectedSkill))) 

其中GetFullyQualifiedName(Object)返回“Company.SelectedEmployee.SelectedSkill”。

问题的第二部分:想象一下,SelectedEmployee为null:有没有办法允许将NullReference传递给方法? 我99.9%肯定答案是否定的:)

我不明白。 为什么不呢:

 private void DeleteSelectedSkillFromSelectedEmployee() { if(Company != null && Company.SelectedEmployee != null && Company.SelectedEmployee.Skills != null) { Company.SelectedEmployee.Skills.Remove(Company.SelectedEmployee.SelectedSkill); EmployeeSkillsListView.ScrollIntoView(Company.SelectedEmployee.Skills.Last()); } } 

或者在C#6中

 if(Company?.SelectedEmployee?.Skills != null) { ... } 

如果您仍然想要使用GetFullyQualifiedName方法,那么您可以使用的最接近的方法(不检查错误,它只是一个快速的黑客):

 public static string GetPathOfProperty(Expression> property) { string resultingString = string.Empty; var p = property.Body as MemberExpression; while (p != null) { resultingString = p.Member.Name + (resultingString != string.Empty ? "." : "") + resultingString; p = p.Expression as MemberExpression; } return resultingString; } 

然后使用它像:

 GetPathOfProperty(() => Foo.Bar.Baz.SomeProperty ); 

这将返回一个包含"Foo.Bar.Baz.SomeProperty"的字符串

在小提琴中检查它