2

リストを辞書に保存するキャッシュクラスがあります。

public class CacheList<T>
{
    private Dictionary<UInt64, T> _cacheItems = new Dictionary<UInt64, T>();

    public IList<T> GetItems()
    {
        return new List<T>(_cacheItems.Values);
    }

    public void Add(T item)
    {
        UInt64 key = (UInt64)(item.GetHashCode());

        if (!_cacheItems.ContainsKey(key))
            _cacheItems.Add(key, item);
    }
}

現在、ジェネリック T からハッシュコードを取得して、項目をディクショナリに追加しています。しかし、キーとして保持するフィールド/プロパティを指定したいと考えています。問題は、タイプ T であるため、このアイテムにどのプロパティがあるかがわからないことです。

一般的なアイテムからプロパティにアクセスするにはどうすればよいですか?

4

3 に答える 3

2

私はジェネリックを見て「制約」を考えましたが、後から考えると、マークのアプローチの方がずっと好きなので、彼のルートに行きます。

必要なプロパティを公開するインターフェイスを作成し、そのインターフェイスに制約することができます。

interface IExposeKey
{
    string Key { get; }
}

public class CacheList<T> where T : IExposeKey { }

コードでは、コンパイラTIExposeKeyそれを想定できるようになったため、それに応じて厳密に型指定されたアクセスを提供できます。

public void Add(T item)
{
    string key = item.Key;

    if (!_cacheItems.ContainsKey(key))
        _cacheItems.Add(key, item);
}

この方法でプロパティ名を公開して、Tインスタンスでリフレクションを使用することもできますが、実行時エラーが発生する可能性があります。

于 2012-07-23T08:20:21.117 に答える
2

多分:

public class CacheList<T, TKey>
{
    private readonly Dictionary<TKey, T> _cacheItems = new Dictionary<TKey, T>();
    private readonly Func<T, TKey> selector;
    public CacheList(Func<T, TKey> selector)
    {
        this.selector = selector;
    }
    public IList<T> GetItems()
    {
        return new List<T>(_cacheItems.Values);
    }

    public bool Add(T item)
    {
        TKey key = selector(item);

        if (_cacheItems.ContainsKey(key)) { return false; }

        _cacheItems.Add(key, item);
        return true;
    }
    public bool TryGetValue(TKey key, out T value)
    {
        return _cacheItems.TryGetValue(key, out value);
    }
}

それで:

var dict = new CacheList<Customer,int>(c => c.CustomerId);
于 2012-07-23T08:22:42.847 に答える
2

ラムダ関数を使用してキーを指定できます。このようなもの:

public class CacheList<T, P>
{
    private Dictionary<P, T> _cacheItems = new Dictionary<P, T>();
    private Func<T, P> _getKey;

    public CacheList(Func<T, P> getKey)
    {
        _getKey = getKey;
    }

    public IList<T> GetItems()
    {
        return new List<T>(_cacheItems.Values);
    }

    public void Add(T item)
    {
        P key = _getKey(item);

        if (!_cacheItems.ContainsKey(key))
            _cacheItems.Add(key, item);
    }
}

次に、次のようにインスタンスを作成します。

var cl = new CacheList<MyClass, string>(x => x.SomeProperty);

これはうまくいきますか?

于 2012-07-23T08:24:12.527 に答える