完全合格的财产名称
我正在尝试阻止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"
的字符串
在小提琴中检查它