如何检查 WCF 配置文件中的两个 XML 元素在功能上是否等效?



我想编写代码以编程方式修改 .NET 配置文件的 WCF 部分。具体来说,我希望能够检查是否存在特定类型的绑定,如果不存在,则添加它。但是,检查现有绑定结果有点棘手。

要检查两个绑定(或一般的两个配置元素(是否相同,以下是规则:

  1. 它们必须具有相同的元素名称(例如<binding>不等同于<behavior>(
  2. 它们可能具有不同的名称属性(例如<binding name="MyBinding">等价于<binding name="YourBinding">,如果其他一切都一样(
  3. 所有其他属性必须具有相同的名称和值,并且一个元素中的每个属性都必须存在于另一个元素中。
  4. 忽略 XML 注释
  5. 所有子元素在两个方向上都必须在比较的元素中具有其等效项。因此,左侧的每个子元素在右侧都必须有一个等效项,反之亦然。
  6. 子元素可能以不同的顺序显示。这对两个元素是否等效没有影响。

我想出了以下代码,它看起来相当蛮力:

static public bool IsEquivalentTo(this XElement source, XElement compareTo)
{
if (source == null && compareTo == null) return true;
if (source == null || compareTo == null) return false;
if (source.Equals(compareTo)) return true;
//Compare element name
if (source.Name != compareTo.Name) return false;
//Compare all attributes except the "Name" attribute (which is different from the element's name proper)
var attributes = source.Attributes().ToDictionary( x => x.Name, x => x.Value);
if (attributes.Count != compareTo.Attributes().Count()) return false;
foreach (var a in attributes)
{
if (a.Key == "name") continue;
if (a.Value != compareTo.Attribute(a.Key).Value) return false;
}
//Compare subelements. Each element on the left must have a matching element on the right. ,and vice versa. 
var lhs = source.Elements().ToList();
var rhs = compareTo.Elements().ToList();
foreach (var l in lhs)
{
bool found = false;
foreach (var r in rhs)
{
if (l.IsEquivalentTo(r))
{
found = true;
break;
}
}
if (!found) return false;
}
foreach (var r in rhs)
{
bool found = false;
foreach (var l in lhs)
{
if (r.IsEquivalentTo(l))
{
found = true;
break;
}
}
if (!found) return false;
}
return true;
}

有没有更简单的方法来实现这一点?

这里有一些测试用例的小提琴,如果你想尝试一下。

如果您需要检查除名称之外的所有元素的相等性,那么我建议您可以为两个元素设置相同的名称并使用类似 XNode.DeepEquals(( 的东西

最新更新