2

サーバーからオブジェクト(作成したカスタムタイプ)を受け取り、ユーザーがオブジェクトを編集してから、「チェンジセット」をサーバーに送信するWindowsストアアプリを作成しています。この変更セットは、ユーザーが編集したフィールドを除くすべてのフィールドが null に設定された、受信したオブジェクトと同じタイプのオブジェクトです。これらのフィールドには、ユーザーの編集が次のように含まれます。

オリジナルケース:
    説明:「ひびの入った排気管」
    ステータス:「オープン」
    お客様: ""
    マイレージ: 10000

編集されたケース:
    説明: ""
    ステータス「オープン」
    お客様:「株式会社例」
    マイレージ: 10000

ケースチェンジセット:
    説明: ""
    ステータス: null
    お客様:「株式会社例」
    マイレージ: null

アプリが最初にサーバーからオブジェクトをダウンロードするときに、後で比較するためにオブジェクトのコピーを作成します。次に、ユーザーがオブジェクトの 1 つに変更を加え、ユーザーが変更を送信すると、これら 2 つのオブジェクトの変更セットがジェネリック メソッドで計算されますCalculateChangeSet。2 つのオブジェクトのすべてのプロパティを調べて、等しいかどうかを比較します。

public static T CalculateChangeSet<T>(T oldObject, T newObject) where T : new()
{
    T changeSet = (T)Activator.CreateInstance(oldObject.GetType());

    foreach (PropertyInfo property in oldObject.GetType().GetRuntimeProperties())
    {
        var oldValue = property.GetValue(oldObject);
        var newValue = newObject.GetType().GetRuntimeProperty(property.Name).GetValue(newObject);
        if (oldValue != null && newValue != null)
        {
            if (oldValue is IList)
            {
                Type listType = oldValue.GetType().GetRuntimeProperty("Item").PropertyType;

                IList<listType> oldList = (IList<listType>)oldValue; //Visual studio complains about
                IList<listType> newList = (IList<listType>)newValue; //listType not being found

                if (!oldList.SequenceEqual(newList))
                {
                    changeSet.GetType().GetRuntimeProperty(property.Name).SetValue(changeSet, newValue, null);
                }
            }
            else
            {
                if (!oldValue.Equals(newValue))
                {
                    changeSet.GetType().GetRuntimeProperty(property.Name).SetValue(changeSet, CalculateChangeSet(oldValue, newValue));
                }
            }
        }
        else
        {
            changeSet.GetType().GetRuntimeProperty(property.Name).SetValue(changeSet, newValue);
        }
    }

    return changeSet;
}

このメソッドは、リストを除くすべてのプロパティで正常に機能するため、リストを処理する if 句を作成しました。list1.Equals(list2)はリスト内の項目を比較しないため、キャストしoldValuenewValue使用List<T>できるようにする必要がありますlist.SequenceEqual()

The type or namespace name 'listType' could not be found (are you missing a using directive or an assembly reference?)それを使用して新しいリストを作成しようとすると、エラーが発生するのはなぜですか? この問題にアプローチするより良い方法があれば、私は提案を受け付けています..

4

1 に答える 1

0

これを試して:

IList oldList = (IList)oldValue; //Visual studio complains about
IList newList = (IList)newValue; //listType not being found

if (!NonGenericSequenceEqual(oldList, newList))
{
    changeSet.GetType().GetRuntimeProperty(property.Name).SetValue(changeSet, newValue, null);
}

public static bool NonGenericSequenceEqual(IList a, IList b)
{
    if (ReferenceEquals(a, b))
    {
        return true;
    }
    else if (a == null || b == null)
    {
        return false;
    }
    else
    {
        int count = a.Count;

        if (count != b.Count)
        {
            return false;
        }
        else
        {
            for (int i = 0; i < count; i++)
            {
                if (!Object.Equals(a[i], b[i]))
                {
                    return false;
                }
            }

            return true;
        }
    }
}

弱いコードは「Object.Equals(a[i], b[i])」です

リフレクションによる別のバリ​​アント:

if (!(bool)typeof(System.Linq.Enumerable).GetMethod("SequenceEqual").MakeGenericMethod(oldValue.GetType().GetRuntimeProperty("Item").PropertyType).Invoke(null, new object[] { oldObject, newObject }))
{
    changeSet.GetType().GetRuntimeProperty(property.Name).SetValue(changeSet, newValue, null);
}
于 2013-04-05T11:16:01.170 に答える