检查 xml 节点是否存在并在 c# 中进行序列化

check if xml node exists with serialization in c#

我有一个程序 运行 可以读取序列化 xml 文件。这些文件来自简历解析服务。由于这些是简历,xml 文件中有很多节点不是必需的,因此我需要在尝试获取它们的值之前检查它们是否存在。问题是我在其中一些上遇到了一些对象引用错误。

这是我目前已有的一些代码的示例

        if (obj.HireAbilityXMLResults.Resume.StructuredXMLResume.References != null)
        {
            string ReferenceName = "";
            string ReferenceAddress = "";
            string ReferencePhone = "";
            string ReferenceRelation = "";
            string areaCode = "";
            string subscriberNumber = "";
            string refCity = "";
            string refState = "";

            var references = obj.HireAbilityXMLResults.Resume.StructuredXMLResume.References;
            foreach (var r in references)
            {
                ReferenceName = r.Reference.PersonName.FormattedName.ToString();
                if (r.Reference.ContactMethod != null)
                {
                    if (r.Reference.ContactMethod.Telephone != null)
                    {
                        if (r.Reference.ContactMethod.Telephone.AreaCityCode != null)
                        {
                            areaCode = r.Reference.ContactMethod.Telephone.AreaCityCode.ToString();
                        }
                        if (r.Reference.ContactMethod.Telephone.SubscriberNumber != null)
                        {
                            subscriberNumber = r.Reference.ContactMethod.Telephone.SubscriberNumber.ToString();
                        }
                        ReferencePhone = areaCode + "-" + subscriberNumber;
                    }
                    if (r.Reference.ContactMethod.PostalAddress != null)
                    {
                        if (r.Reference.ContactMethod.PostalAddress.Municipality != null)
                        {
                            refCity = r.Reference.ContactMethod.PostalAddress.Municipality.ToString();
                        }
                        if (r.Reference.ContactMethod.PostalAddress.Region != null)
                        {
                            refState = r.Reference.ContactMethod.PostalAddress.Region.ToString();
                        }
                        ReferenceAddress = refCity + "," + refState;
                    }
                }
                if (r.Reference.PositionTitle != null)
                {
                    ReferenceRelation = r.Reference.PositionTitle.ToString();
                }
                ProfessionalReferences proRefs = new ProfessionalReferences();
                proRefs.Add(UserID, ReferenceName.LimitLength(50), ReferencePhone, ReferenceAddress.LimitLength(50), ReferenceRelation.LimitLength(20), x);
                x++;
            }

        }

我遇到的问题是,如果节点不存在,我会收到错误消息,提示“对象引用未设置为对象的实例。”

为了争论起见,假设有人将 John Smith Chicago 列为可能的参考,但没有放入 IL,因此该节点将不存在 r.Reference.ContactMethod.PostalAddress.Region 然后这一行将抛出错误

if (r.Reference.ContactMethod.PostalAddress.Region != null)

我读到一个答案,其中有人说使用 is object 而不是像这样

if (r.Reference.ContactMethod.PostalAddress.Region is object)

这是确保节点存在的正确方法吗?

使用Null-Conditional Operator:

if (r?.Reference?.ContactMethod?.PostalAddress?.Region != null)

这将传播空值而不是抛出空引用异常。

顺便说一句,大量成员访问运算符连续出现 (r.Reference.ContactMethod.PostalAddress.Region) 是一种代码味道。它充满了设计不佳的数据结构,DRY principle violations and violations of the Law of Demeter

您需要将代码的概念封装到方法中。问问自己,“我想要完成什么?”并创建一个具有该名称的方法。例如,您的代码似乎正在检查引用是否具有有效的联系信息。所以 Reference 应该有一个名为 HasValidContactInformation:

的方法
class Reference
{
     public bool HasValidContactInformation()
     {
          //you write your implementation here
     }
}

如果你发现自己的深度超过 1 或 2 个点(field/property 访问运算符),你应该考虑将你的逻辑封装到一个方法中。