Я пытаюсь написать метод сравнения для сравнения свойств в некоторых POCOs с использованием Reflection, чтобы убедиться, что они были сохранены в базе данных правильно. Например, предположим, что у меня есть этот ПОКО:Как преобразовать объект из Reflection в общую коллекцию?
public class NoahsArk
{
public string Owner { get; set; }
public ICollection<Animal> Animals { get; set; }
}
То, что я хочу сделать это:
[Test]
public class Saves_Correctly_To_Database()
{
var noahsArk = new NoahsArk { // some setup code here };
db.Save(noahsArk);
var dbNoahsArk = db.Get<NoahsArk>(noahsArk.Id);
Assert.That(Compare(noahsArk, dbNoahsArk), Is.True);
}
ORM так я использую NHibernate. Мой метод сравнения выглядит следующим образом до сих пор:
public static bool EqualsProperties<T>(this T x, T y)
{
var xType = x.GetType();
foreach (var property in xType.GetProperties())
{
if (property.GetValue(x, null).Implements(typeof(ICollection<>)))
{
var xValue = property.GetValue(x, null) as ICollection<T>;
var yValue = property.GetValue(y, null) as ICollection<T>;
}
Object.Implements()
является метод расширения я написал, чтобы определить, если тип реализует интерфейс. Как видите, метод неполный. Проблема, с которой я сталкиваюсь, заключается в том, что, когда я использую property.GetValue(x, null)
, он возвращает object
, и я не знаю, как отличить его в свой общий тип ICollection
. Мне нужно сделать это, чтобы я мог использовать LINQ, чтобы сделать x.Contains(y)
, чтобы сравнить две коллекции для равенства. Любая идея о том, как это сделать?
P.S. Я пробовал использовать Compare .NET Objects, но он дает мне исключение с ссылкой на null где-то глубоко в NHibernate. Он неправильно обрабатывает, как NHibernate проксирует ICollection
для ленивой загрузки. Хуже того, NHibernate модифицирует POCO для поддержки ленивой загрузки, но все это делается во время выполнения. В исходном коде похоже, что вы просто работаете с обычным ICollection
, но NHibernate меняет это на NHibernate.Collections.Generic.PersistentSet
во время выполнения, и это то, что приводит к сбою компаратора.
Спасибо за ваш ответ. Мое мышление по поводу использования параметра типа T в объявлении заключалось в том, что это служит неявной первой проверкой того, что вы должны передать два объекта одного типа, иначе компилятор скажет, что он не может неявно преобразовать один из них в тип Т. –