我一直在寻找一段代码,这些代码可以做类似的事情来帮助编写单元测试。这是我最终使用的内容。
public static bool PublicInstancePropertiesEqual<T>(T self, T to, params string[] ignore) where T : class { if (self != null && to != null) { Type type = typeof(T); List<string> ignoreList = new List<string>(ignore); foreach (System.Reflection.PropertyInfo pi in type.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)) {if (!ignoreList.Contains(pi.Name)){ object selfValue = type.GetProperty(pi.Name).GetValue(self, null); object toValue = type.GetProperty(pi.Name).GetValue(to, null); if (selfValue != toValue && (selfValue == null || !selfValue.Equals(toValue))) { return false; }} } return true; } return self == to; }编辑:
与上面相同的代码,但使用LINQ和Extension方法:
public static bool PublicInstancePropertiesEqual<T>(this T self, T to, params string[] ignore) where T : class{ if (self != null && to != null) { var type = typeof(T); var ignoreList = new List<string>(ignore); var unequalProperties = from pi in type.GetProperties(BindingFlags.Public | BindingFlags.Instance) where !ignoreList.Contains(pi.Name) && pi.GetUnderlyingType().IsSimpleType() && pi.GetIndexParameters().Length == 0 let selfValue = type.GetProperty(pi.Name).GetValue(self, null) let toValue = type.GetProperty(pi.Name).GetValue(to, null) where selfValue != toValue && (selfValue == null || !selfValue.Equals(toValue)) select selfValue; return !unequalProperties.Any(); } return self == to;}public static class TypeExtensions { /// <summary> /// Determine whether a type is simple (String, Decimal, DateTime, etc) /// or complex (i.e. custom class with public properties and methods). /// </summary> /// <see cref="http://stackoverflow.com/questions/2442534/how-to-test-if-type-is-primitive"/> public static bool IsSimpleType( this Type type) { return type.IsValueType || type.IsPrimitive || new[] { typeof(String), typeof(Decimal), typeof(DateTime), typeof(DateTimeOffset), typeof(TimeSpan), typeof(Guid) }.Contains(type) || (Convert.GetTypeCode(type) != TypeCode.Object); } public static Type GetUnderlyingType(this MemberInfo member) { switch (member.MemberType) { case MemberTypes.Event: return ((EventInfo)member).EventHandlerType; case MemberTypes.Field: return ((FieldInfo)member).FieldType; case MemberTypes.Method: return ((MethodInfo)member).ReturnType; case MemberTypes.Property: return ((PropertyInfo)member).PropertyType; default: throw new ArgumentException ( "Input MemberInfo must be if type EventInfo, FieldInfo, MethodInfo, or PropertyInfo" ); } } }


