Il metodo di estensione .AsQueryable()
restituisce un'istanza della EnumerableQuery<T>
wrapper class se viene chiamato su qualcosa che non fosse già un IQueryable<T>
.
classe Questo wrapper ha una proprietà .Enumerable
con internal
di accesso che fornisce l'accesso all'oggetto originale che .AsQueryable()
è stato chiamato su. Così si potrebbe fare questo per ottenere indietro il dizionario originale:
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
}
Tuttavia, questa è generalmente una brutta idea. internal
i membri hanno il loro accesso limitato per un motivo, e non credo che ci sia alcuna garanzia che l'implementazione interna di .AsQueryable()
non cambierà ad un certo punto in futuro. Quindi la soluzione migliore è trovare un modo per rendere accessibile il dizionario originale o procedere e crearne uno nuovo.
Una soluzione possibile (che non è grande) è quello di rendere la propria classe wrapper per portare il dizionario lungo:
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; }
}
}
Si tratterebbe sia di agire come un wrapper per IQueryable<T>
e fornire l'accesso del dizionario al dizionario originale . Ma d'altra parte, chiunque cerchi di recuperare il dizionario dovrebbe sapere quali sono i parametri di tipo generico sono stati (per esempio <string, string>
, <int, string>
, etc.) al fine di lanciare con successo.
Il suggerimento con il 'campo privato Enumerable' lavorato.Ho anche incluso un fallback nel mio codice ('if (pInfo == null) quindi creare un nuovo dizionario e aggiungere manualmente KeyValuePairs') per mantenere la compatibilità con le versioni future. –