C# 完全限定属性名

C# 完全限定属性名,c#,nullreferenceexception,C#,Nullreferenceexception,我正在尝试阻止System.NullReferenceException 我有一家公司,有一群员工。每个员工都有一套技能 SelectedEmployee指向Employee集合中当前选定的元素 SelectedSkill指向技能集合中当前选定的元素 我有一个ListView,它的ItemSource绑定到技能集合; ListView的SelectedItem绑定到SelectedSkill 当技能被删除时,我希望ListView滚动到最后一个元素 private void DeleteSele

我正在尝试阻止System.NullReferenceException

我有一家公司,有一群员工。每个员工都有一套技能

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

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

我有一个ListView,它的ItemSource绑定到技能集合; ListView的SelectedItem绑定到SelectedSkill

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

private void DeleteSelectedSkillFromSelectedEmployee()
{
    Company.SelectedEmployee.Skills.Remove(Company.SelectedEmployee.SelectedSkill);
    EmployeeSkillsListView.ScrollIntoView(Company.SelectedEmployee.Skills.Last());
}
如果未选择员工,则SelectedEmployee将为空。在方法内部执行任何操作时,这将导致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)))
其中GetFullyQualifiedNameObject返回Company.SelectedEmployee.SelectedSkill

问题的第二部分:假设SelectedEmployee为null:有没有办法允许将null引用传递给方法?
我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());
  }
}
或者在C6中

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;           
}
这将返回一个包含Foo.Bar.Baz.SomeProperty的字符串


我不明白。为什么不只是:

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());
  }
}
或者在C6中

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;           
}
这将返回一个包含Foo.Bar.Baz.SomeProperty的字符串


你为什么要费心思考?为什么不直接查看公司。SelectedEmployee!=空?假设一个属性有n个部分;其中任何一个都可以为空。A.B.C.D.E.F.G.H.精选技能。我不想用一个巨大的If语句来检查每一个。你为什么要费心思考呢?为什么不直接查看公司。SelectedEmployee!=空?假设一个属性有n个部分;其中任何一个都可以为空。A.B.C.D.E.F.G.H.精选技能。我不想用一个庞大的If语句来检查每一个。可能还应该检查Company.SelectedEmployee.Skills以确保完整性。感谢您的回复。我不知道那是什么?在if语句中使用。但是,正如我所提到的,代码只是一个示例,实际使用的可能更多。selected.selected.selected.selected。。等等,我试图找到一种不产生巨大If语句的方法。能够找到一个属性的完全限定名对我来说在很多地方都很有用。有什么想法吗?@James房产没有完全限定的名称。类型有一个程序集限定名,但其中包括区域性、版本等,而这可能不是您要考虑的。在任何情况下,使用?。空传播操作数在C 6中,使用字符串执行的任何操作都更容易出现重构错误,并且基本上什么也得不到?对于第二个问题,每个点都不是一个问题,答案是不,不存在这样的问题,您可以使用和解析linq表达式来伪造它,如GetNameForProperty=>Property.Subperty.ChildProperty,但同样,不值得麻烦和运行时性能损失。。。在C6中,您可以使用nameofproperty,但这只返回属性/类型/字段的名称,如果您想将其命名为soYeah,则不返回其完整路径,我想是这样的。谢谢我已经调查了一段时间,并认为这是没有办法的,但我想我会把它扔出去,以防有什么很酷的东西我可以抓住它。我肯定会用这个?。为了替换反射。可能还应该检查Company.SelectedEmployee.Skills以确保完整性。感谢您的回复。我不知道那是什么?在if语句中使用。但是,正如我所提到的,代码只是一个示例,实际使用的可能更多。selected.selected.selected.selected。。等等,我试图找到一种不产生巨大If语句的方法。能够找到一个属性的完全限定名对我来说在很多地方都很有用。有什么想法吗?@James房产没有完全限定的名称。类型有一个程序集限定名,但其中包括区域性、版本等,而这可能不是您要考虑的。在任何情况下,使用?。中的空传播操作数
在C 6中,使用字符串所做的任何事情都更容易出现重构错误,并且基本上什么也得不到?对于第二个问题,每个点都不是一个问题,答案是不,不存在这样的问题,您可以使用和解析linq表达式来伪造它,如GetNameForProperty=>Property.Subperty.ChildProperty,但同样,不值得麻烦和运行时性能损失。。。在C6中,您可以使用nameofproperty,但这只返回属性/类型/字段的名称,如果您想将其命名为soYeah,则不返回其完整路径,我想是这样的。谢谢我已经调查了一段时间,并认为这是没有办法的,但我想我会把它扔出去,以防有什么很酷的东西我可以抓住它。我肯定会用这个?。以取代反射。