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

我看到了泛型并想到了“约束”,但事后看来,我更喜欢Marc 的方法,所以我会走他的路。

您可以创建一个接口来公开您需要的属性,然后在该接口上进行约束:

interface IExposeKey
{
    string Key { get; }
}

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

在代码中,编译器现在可以假设T可以IExposeKey相应地提供强类型访问:

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

您可以使用 lambda 函数来指定密钥。像这样的东西:

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 回答