質問

私は自分のデータエンティティとなるクラスのリストをシリアライズしています。私はリストが含まれているデータプロバイダを持っています。

私は常にコレクション内のアイテムを直接変更します。

リストに項目が変更されているかどうかを決定する最良の方法は何ですか?私は、Compact Frameworkのを使用しています。

私の唯一の現在の考えは、(それが可能の場合)私はリストを読み込むときに、リストのハッシュを作成することです。その後、私はときに私が保存リストのハッシュを再取得し、彼らは異なる値をしているかどうかを確認します。それらが異なるなら、私は、彼らはその後、同じことをしている場合、私は保存しない、保存して後で比較するために保存されたハッシュを更新します。

任意のアイデア?

役に立ちましたか?

解決

あなたがリストに追加アイテムが実装する場合 INotifyPropertyChanged インタフェース、あなたはアイテムがリストから削除されたイベントをリストに追加するすべてのオブジェクトについて、そのインタフェースでイベントをフックし、unhooks独自のジェネリックリストを構築することができます。

があり BindingList<T> のクラスには、使用可能な枠組みの中でだ、またはあなたがあなた自身を書くことができます。

ここではタイプがwhere T: INotifyPropertyChangedで宣言されたと仮定すると、サンプルaddメソッドです

public void Add(T item)
{
    // null-check omitted for simplicity
    item.PropertyChanged += ItemPropertyChanged;
    _List.Add(item);
}

this[index]インデクサプロパティます:

public T this[Int32 index]
{
    get { return _List[index]; }
    set {
        T oldItem = _List[index];
        _List[index] = value;
        if (oldItem != value)
        {
            if (oldItem != null)
                oldItem.PropertyChanged -= ItemPropertyChanged;
            if (value != null)
                value.PropertyChanged += ItemPropertyChanged;
        }
    }
}

あなたのアイテムがINotifyPropertyChangedをサポートしていませんが、彼らはあなたのクラスをしている場合は、私はそのサポートを追加することを検討します。

他のヒント

あなたがあなた自身のIList<T>クラスを作成することができ、リストが変更されたときに記録することができDirtyList<T>を言ってます。

あなたはリフレクションを使用して喜んでいる場合は、

List<T>クラスは、リストが変わるたびにインクリメントされ_versionというプライベートフィールドがあります。これは、アイテムが変更されているを教えてくれませんが、未修正のリストを検出する_versionの元の値と比較することができます。

参考のために、このフィールドは、リストが変更されたときに列挙子が無効になることを保証するために使用されます。だから、List<T>の変更のための実際のマネージコードがない限り、かなり確実にあなたの目的のためにそれを使用することができる必要があります。

_versionの値は、あなたがこのようなものを使用することができます取得するには:

List<T> myList;
var field = myList.GetType().GetField("_version", BindingFlags.Instance | BindingFlags.NonPublic);
int version = field.GetValue(myList);

一般的に言って、しかし、これが最善のアプローチではありません。あなたが他の人が作成したList<T>を使用して立ち往生している場合は、しかし、それはおそらくあなたが持っている最高のオプションです。 .NETフレームワークへの変更は、フィールドの名前を変更(またはそれを完全に削除します)、そしてモノのようなサードパーティ製のCLRの実装に存在することが保証されていない可能性がありますのでご注意ください。

どのようにこのようなものでしょうか?

public class ItemChangedArgs<T> : EventArgs
{
    public int Index { get; set; }
    public T Item { get; set; }
}

public class EventList<T> : IList<T>, ICollection<T>, IEnumerable<T>, IEnumerable
{
    private List<T> m_list;
    public event EventHandler<ItemChangedArgs<T>> ItemAdded;
    public event EventHandler<ItemChangedArgs<T>> ItemRemoved;
    public event EventHandler<ItemChangedArgs<T>> ItemChanged;
    public event EventHandler ListCleared;

    public EventList(IEnumerable<T> collection)
    {
        m_list = new List<T>(collection);
    }

    public EventList(int capacity)
    {
        m_list = new List<T>(capacity);
    }

    public EventList()
    {
        m_list = new List<T>();
    }

    public void Add(T item)
    {
        Add(item, true);
    }

    public void Add(T item, Boolean raiseEvent)
    {
        m_list.Add(item);
        if (raiseEvent) RaiseItemAdded(this.Count - 1, item);
    }

    public void AddRange(IEnumerable<T> collection)
    {
        foreach (T t in collection)
        {
            m_list.Add(t);
        }
    }

    private void RaiseItemAdded(int index, T item)
    {
        if (ItemAdded == null) return;

        ItemAdded(this, new ItemChangedArgs<T> { Index = index, Item = item });
    }

    public int IndexOf(T item)
    {
        return m_list.IndexOf(item);
    }

    public void Insert(int index, T item)
    {
        m_list.Insert(index, item);
        RaiseItemAdded(index, item);
    }

    public void RemoveAt(int index)
    {
        T item = m_list[index];
        m_list.RemoveAt(index);
        RaiseItemRemoved(index, item);
    }

    private void RaiseItemRemoved(int index, T item)
    {
        if(ItemRemoved == null) return;
        ItemRemoved(this, new ItemChangedArgs<T> { Index = index, Item = item });
    }

    public T this[int index]
    {
        get { return m_list[index]; }
        set 
        { 
            m_list[index] = value;
            RaiseItemChanged(index, m_list[index]);
        }
    }

    private void RaiseItemChanged(int index, T item)
    {
        if(ItemChanged == null) return;
        ItemChanged(this, new ItemChangedArgs<T> { Index = index, Item = item });
    }

    public void Clear()
    {
        m_list.Clear();
        RaiseListCleared();
    }

    private void RaiseListCleared()
    {
        if(ListCleared == null) return;
        ListCleared(this, null);
    }

    public bool Contains(T item)
    {
        return m_list.Contains(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        m_list.CopyTo(array, arrayIndex);
    }

    public int Count
    {
        get { return m_list.Count; }
    }

    public bool IsReadOnly
    {
        get { return false; }
    }

    public bool Remove(T item)
    {
        for (int i = 0; i < m_list.Count; i++)
        {
            if(item.Equals(m_list[i]))
            {
                T value = m_list[i];
                m_list.RemoveAt(i);
                RaiseItemRemoved(i, value);
                return true;
            }
        }
        return false;
    }

    public IEnumerator<T> GetEnumerator()
    {
        return m_list.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return m_list.GetEnumerator();
    }
}

リストに含まれるすべてのメンバーのために適切に実装(したがって際の要素の変更変更)されGetHashCodeメソッド()私はの線に沿って何かを想像すると仮定します:

public class DirtyList<T> : List<T> {
    private IList<int> hashCodes = new List<int> hashCodes();
    public DirtyList() : base() { }
    public DirtyList(IEnumerable<T> items) : base() {
        foreach(T item in items){
            this.Add(item); //Add it to the collection
            hashCodes.Add(item.GetHashCode());
        }
    }

    public override void Add(T item){
        base.Add(item);
        hashCodes.Add(item);
    }
    //Add more logic for the setter and also handle the case where items are removed and indexes change and etc, also what happens in case of null values?

    public bool IsDirty {
       get {
           for(int i = 0; i < Count: i++){
               if(hashCodes[i] != this[i].GetHashCode()){ return true; }
           }
           return false;
       }
    }
}

*私はSOにこれを入力したと述べたコードが動作するようにguarenteedでは決してない上記のように、コンパイラを持っていないに注意して、うまくいけば、それはアイデアを紹介してください。

あなたがしている例えば2つの内部リストを維持独自のリスト...およびインスタンス化バージョンと追跡バージョンを...実装することができます。

//Rough Psuedo Code
public class TrackedList<T> : List<T>
{
    public bool StartTracking {get; set; }
    private List<T> InitialList { get; set; }

    CTOR
    {
        //Instantiate Both Lists...
    }

    ADD(item)
    {
        if(!StartTracking)
        {
            Base.Add(item);
            InitialList.Add(item);
        }
        else
        {
            Base.Add(item);
        }
    }

    public bool IsDirty
    {
       get
       {
           Check if theres any differences between initial list and self.
       }
    }
}

Tはダーティフラグを持つオブジェクトの子孫であることを確認し、リストの汚れフラグを歩くそのためのチェックを持っているIList実装を持っています。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top