Powiedzmy mam taką strukturęWzór dostać obiektów o strukturze różnicę i statystyki czyli jak stworzyć diff narzędzie
public class Form
{
#region Public Properties
public List<Field> Fields { get; set; }
public string Id { get; set; }
public string Name { get; set; }
public string Version { get; set; }
public int Revision { get; set; }
#endregion
}
Więc klasa Form
zawiera listę pól, powiedzmy, że samo pole jest reprezentowane przez takie struktura
public class Field
{
#region Public Properties
public string DisplayName { get; set; }
public List<Field> Fields { get; set; }
public string Id { get; set; }
public FieldKind Type { get; set; }
public FieldType FieldType { get; set; }
#endregion
}
The Field
jest zasadniczo struktura kompozytowa, każdy Field
zawiera listę pól podrzędnych. Struktura jest więc hierarchiczna. Również Field ma odniesienie do klasy FieldType
.
public class FieldType
{
#region Public Properties
public DataType DataType { get; set; }
public string DisplayName { get; set; }
public string Id { get; set; }
#endregion
}
I na koniec mamy odniesienie do DataType
public class DataType
{
#region Public Properties
public string BaseType { get; set; }
public string Id { get; set; }
public string Name { get; set; }
public List<Restriction> Restrictions { get; set; }
#endregion
}
Co chcę osiągnąć jest uzyskanie różnicy takiej skomplikowanej strukturze, powiedzmy, że jeśli mam jakąś porównywarka Będzie daj mi strukturalną różnicę dla całej formy jako jednej klasy, powiedzmy RóżnicaRezult. Kiedy mówiłem o strukturalnej różnicy, mam na myśli, że powinno to być coś takiego.
- Różnica dla pól
Form
(wyjścieForm
ma różnicy w polu Wersja (inny kolor) - Różnice w zakresie zbierania
Fields
, w tym hierarchii pola do pola pod redakcją - samo zachowanie dla
FieldType
iDataType
- Wykrywanie usuwanie i dodawanie
Field
doForm
(więc zapewne każdy Różnica będzie miał typ)
Co mam teraz. Zacząłem ogólne podejście i próbowali wykorzystać ReflectionComparer realizacji sprzęgowi IEqualityComparer
public bool Equals(T x, T y)
{
var type = typeof(T);
if (typeof(IEquatable<T>).IsAssignableFrom(type))
{
return EqualityComparer<T>.Default.Equals(x, y);
}
var enumerableType = type.GetInterface(typeof(IEnumerable<>).FullName);
if (enumerableType != null)
{
var elementType = enumerableType.GetGenericArguments()[0];
var elementComparerType = typeof(DifferenceComparer<>).MakeGenericType(elementType);
var elementComparer = Activator.CreateInstance(elementComparerType, new object[] { _foundDifferenceCallback, _existedDifference });
return (bool)typeof(Enumerable).GetGenericMethod("SequenceEqual", new[] { typeof(IEnumerable<>), typeof(IEnumerable<>), typeof(IEqualityComparer<>) }).MakeGenericMethod(elementType).Invoke(null, new[] { x, y, elementComparer });
}
foreach (var propertyInfo in type.GetProperties())
{
var leftValue = propertyInfo.GetValue(x);
var rightValue = propertyInfo.GetValue(y);
if (leftValue != null)
{
var propertyComparerType = typeof(DifferenceComparer<>).MakeGenericType(propertyInfo.PropertyType);
var propertyComparer = Activator.CreateInstance(propertyComparerType, new object[] {_foundDifferenceCallback, _existedDifference});
if (!((bool)typeof(IEqualityComparer<>).MakeGenericType(propertyInfo.PropertyType)
.GetMethod("Equals")
.Invoke(propertyComparer, new object[] { leftValue, rightValue })))
{
// Create and publish the difference with its Type
}
}
else
{
if (!Equals(leftValue, rightValue))
{
// Create and publish the difference with its Type
}
}
}
//return true if no differences are found
}
I Difference
klasę
public struct Difference
{
public readonly string Property;
public readonly DifferenceType Type;
public readonly IExtractionable Expected;
public readonly IExtractionable Actual;
}
Ale prawdopodobnie nie jest to sposób, w jaki chcę iść, bo mam porównanie Pole ściślej biorąc w biorąc pod uwagę, że każde pole ma identyfikator, który może być różny również dla różnych formularzy i chcę przejąć większą kontrolę nad procesem porównywania. Dla mnie brzmi to bardziej jak narzędzie do porównywania.
Poszukuję więc dobrego wzoru i całkiem dobrej struktury, aby opublikować różnicę w kodzie klienta, która może z łatwością ją zwizualizować?
Dlaczego zdecydowałeś się do nas e odbicie na pierwszym miejscu? Twoje zajęcia są znane i mocno napisane. Czy planujesz użyć tego również na innych zajęciach? – Groo
Może to pytanie SO jest powiązane z twoim: [link do pytania SO] (http://stackoverflow.com/questions/2387946/finding-property-differences-between-two-c-sharp-objects) i nawet jeśli podane Odpowiedź jest przydatna, bardzo polecam zajrzeć do drugiej odpowiedzi, która wskazuje na [testapi.codeplex.com] (http://testapi.codeplex.com/), która ma "API głębokiego porównywania obiektów" opisaną w części 8. – jCoder
dobrze, niezupełnie, nie ma innych zajęć w tej chwili. pomysł polegał na stworzeniu elastycznego rozwiązania, które następnie może być wykorzystane w przyszłości do porównania również innych klas, więc najpierw spróbowałem refleksji. –