完全合格的财产名称

时间:2016-03-15 10:53:39

标签: c# nullreferenceexception

我试图阻止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不为空)

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

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

GetFullyQualifiedName(Object)返回" Company.SelectedEmployee.SelectedSkill"。

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

1 个答案:

答案 0 :(得分:4)

我不明白。为什么不呢:

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<T>(Expression<Func<T>> 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"

的字符串

Check it in a Fiddle