.AsQueryable() 扩展方法返回一个 EnumerableQuery<T> wrapper class 的实例,如果它被调用的对象还不是 IQueryable<T>。
这个包装类有一个.Enumerable 属性和internal 访问,提供对调用.AsQueryable() 的原始对象的访问。所以你可以这样做来取回你原来的字典:
var dict = new Dictionary<int, int>();
dict.Add(1,1);
var q = dict.AsQueryable();
Type tInfo = q.GetType();
PropertyInfo pInfo = tInfo.GetProperties(BindingFlags.NonPublic |
BindingFlags.Instance)
.FirstOrDefault(p => p.Name == "Enumerable");
if (pInfo != null)
{
object originalDictionary = pInfo.GetValue(q, null);
Console.WriteLine(dict == originalDictionary); // true
}
但是,这通常是一个非常糟糕的主意。 internal 成员的访问受限是有原因的,我认为不能保证 .AsQueryable() 的内部实现在将来的某个时候不会改变。所以你最好的选择是要么找到一种方法让原始字典可以访问,要么继续制作一个新字典。
一种可能的解决方法(不是很好)是制作自己的包装类来携带字典:
private class DictionaryQueryHolder<TKey, TValue> : IQueryable<KeyValuePair<TKey, TValue>>
{
public IDictionary<TKey, TValue> Dictionary { get; private set; }
private IQueryable<KeyValuePair<TKey, TValue>> Queryable { get; set; }
internal DictionaryQueryHolder(IDictionary<TKey, TValue> dictionary)
{
Dictionary = dictionary;
Queryable = dictionary.AsQueryable();
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return Queryable.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public Expression Expression
{
get { return Queryable.Expression; }
}
public Type ElementType
{
get { return Queryable.ElementType; }
}
public IQueryProvider Provider
{
get { return Queryable.Provider; }
}
}
这既可以作为字典IQueryable<T> 的包装器,又可以提供对原始字典的访问。但另一方面,任何试图检索字典的人都必须知道泛型类型参数是什么(例如<string, string>、<int, string> 等)才能成功转换。