我有一个缓存类,它将列表存储到字典中:
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中获取Hashcode来向字典添加项目。但是我想指定我想要哪个字段/属性作为键。问题是它是一个类型T,所以它不知道这个项目中有哪些属性。
如何从通用项目访问属性?
答案 0 :(得分:2)
我看到了仿制品和思想“约束”,但事后我更喜欢Marc's approach,所以我会走他的路。
您可以创建一个接口,公开您需要的属性,然后约束该接口:
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
实例上使用反射,但是您为运行时错误打开了大门。
答案 1 :(得分: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);
答案 2 :(得分: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);
这对你有用吗?