2014-03-07 71 views
3

我有一个方法返回一个巨大的对象与很多领域。类似这样的:模糊深度对象比较

{ 
    Success: true, 
    Timestamp: "07.03.2014", 
    Items: 
    [ 
     { 
      Name: "A", 
      Price: 13.37, 
      OtherData: 123 
     }, 
     { 
      Name: "B", 
      Price: 42, 
      OtherData: 312 
     } 
    ] 
} 

我想比较它的返回值与.NET应用程序中测试的参考值。但是,这里有几个问题:

  • Timestamp场每次
  • 改变Price领域的圆滑也可以改变
  • Items的顺序并不重要

我会喜欢用最灵活的方式定义参考对象:

  • 个省略不必要的字段
  • 能够指定不仅值,但规则(字符串正则表达式,范围/四舍五入的号码等)

这里的参考定义应该如何看起来像一个例子:

{ 
    Success: true, 
    Items: 
    [ 
     { 
      Name: "A", 
      Price: "13.37", 
     }, 
     { 
      Name: "B", 
      Price: 42, 
     } 
    ] 
} 

是否有任何类型的.NET库,允许这种比较?

回答

2

最后我决定自己实施比较。下面的代码,也许这将是使用的人:

public static class Utils 
{ 
    public static bool SequencesMatch<TSource, TPattern>(IEnumerable<TSource> sequence, IEnumerable<TPattern> patterns, Func<TSource, TPattern, bool> matcher) 
    { 
     var items = sequence.Select(x => new SequenceItem<TSource>(x)).ToArray(); 
     var pats = patterns.Select(x => new SequenceItem<TPattern>(x)).ToArray(); 

     foreach (var item in items) 
     { 
      foreach (var pat in pats) 
      { 
       if (pat.Matched) continue; 
       if (matcher(item.Value, pat.Value)) 
       { 
        item.Matched = pat.Matched = true; 
        break; 
       } 
      } 
     } 

     return items.All(x => x.Matched) && pats.All(x => x.Matched); 
    } 

    public static bool JsonObjectsMatch(JToken data, JToken reference) 
    { 
     if (reference.Type == JTokenType.Array) 
      return SequencesMatch(data, reference, JsonObjectsMatch); 

     if (reference.Type == JTokenType.Object) 
     { 
      var dataObj = data as JObject; 
      var refObj = reference as JObject; 

      if (dataObj == null || refObj == null) 
       Assert.Fail("DataObject = '{0}', ReferenceObject = '{1}'", dataObj, refObj); 

      foreach (var pty in refObj) 
      { 
       var dataValue = dataObj[pty.Key]; 
       if (dataValue == null || !JsonObjectsMatch(dataValue, pty.Value)) 
        Assert.Fail("Objects differ at {0}: DataValue = '{1}', RefValue = '{2}'", pty.Key, dataValue, pty.Value); 
      } 

      return true; 
     } 

     if (reference.Type == JTokenType.Float) 
     { 
      var refFloat = reference.ToObject<float>(); 
      var dataFloat = data.ToObject<float>(); 

      if(Math.Abs(dataFloat - refFloat) > 0.001) 
       Assert.Fail("Objects differ: DataValue = '{0}', RefValue = '{1}'", dataFloat, refFloat); 

      return true; 
     } 

     return JToken.DeepEquals(data, reference); 
    } 

    private class SequenceItem<T> 
    { 
     public T Value { get; set; } 
     public bool Matched { get; set; } 

     public SequenceItem(T value) 
     { 
      Value = value; 
     } 
    } 
} 

我也许应该让它在GitHub上一个适当的库和后期一旦我有足够的时间。

+0

是的,你应该。我可以看到这个函数的一些用例:) – ForNeVeR