4

Reflectionを使用して一部のPOCOのプロパティを比較し、データベースに正しく永続化されていることを確認するCompareメソッドを作成しようとしています。たとえば、私がこのPOCOを持っているとしましょう:

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です。私のCompareメソッドは、これまでのところ次のようになっています。

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にキャストする方法がわからないことです。LINQを使用して2つのコレクションが等しいICollectionかどうかを比較できるように、これを実行できる必要があります。x.Contains(y)これを行う方法について何かアイデアはありますか?

PS Compare .NET Objectsを使用しようとしましたが、NHibernateの奥深くでnull参照例外が発生します。ICollectionNHibernateが遅延読み込みのためにプロキシする方法を適切に処理しません。さらに悪いことに、NHibernateは遅延読み込みをサポートするようにPOCOを変更しますが、これはすべて実行時に行われます。ソースコードでは、通常のを使用しているように見えますがICollection、NHibernateはこれをNHibernate.Collections.Generic.PersistentSet実行時に変更します。これが、比較機能の失敗の原因です。

4

2 に答える 2

2

EqualsPropertiesメソッドの宣言に型パラメーターTは必要ないため、質問は少し混乱します。あなたはただ必要です

public static bool EqualsProperties(this object x, object y)

次に、同じパラメータTを使用して、xとyのプロパティをICollection<T>;にキャストします。ただし、これらのコレクション内のオブジェクトは、明らかにxおよびyとは異なるタイプである可能性があります。

ここで、質問に答えます。LINQContainsメソッドを使用するために、正しいジェネリック型にキャストする必要はありません。あなたはこのようなことをすることができます:

xValue = property.GetValue(x, null);
yValue = property.GetValue(y, null);
if (typeof(IEnumerable).IsInstanceOf(x))
{
   IEnumerable<object> xEnumerable = (x as IEnumerable).Cast<object>();
   IEnumerable<object> yEnumerable = (y as IEnumerable).Cast<object>();
   // use any LINQ method you like now
}

ドメインオブジェクトは明らかにEqualsメソッド自体をオーバーライドしないため、等式比較子を使用するLINQオーバーロードを使用することも確認する必要があります。そうでなければ、それらを比較するためにこの単体テストコードを書くことはありません。

于 2009-11-11T00:47:21.253 に答える
0

シャープアーキテクチャフレームワークは、属性を使用してプロパティを装飾します。これは、equalsメソッドに取り込む必要があります。DomainSignatureAttributeクラスとEntityWithTypedId<>.Equalsメソッドのソースコードを参照してください。

于 2009-11-15T10:03:30.287 に答える