当我不知道值的类型时枚举 IDictionary 的键和值
Enumerate keys and values of IDictionary when I don't know type of values
我有一个对象的引用。我知道它符合
IDictionary<string, T>
对于某些类型 T。(它可能不符合普通 IDictionary 或 IReadyOnlyDictionary)。我所知道的关于 T 的是它从 object 派生而来。我怎样才能得到它的键,并得到一个键的值? (我可以将值作为对象而不是 T 返回。我也可以从不了解 T 是什么。)
想写却写不出来的是这样的:
public void SomeMethod(object reallyADict) { // reallyADict implements IDictionary<string, T>.
foreach (string key in reallyADict.Keys) {
object value = reallyADict[key];
// . . .
}
}
**
根据请求,下面是示例 class。
using System;
using System.Collections.Generic;
using System.Collections;
namespace My.Collections
{
public class WrappedDictionary: IDictionary<string, int>
{
public WrappedDictionary() {
this.InnerDictionary = new Dictionary<string, int>{ {"one", 1}, {"two", 2 }};
}
private Dictionary<string, int> InnerDictionary { get; set;}
private ICollection<KeyValuePair<string, int>> InnerCollection {
get {
return this.InnerDictionary;
}
}
#region IDictionary implementation
void IDictionary<string, int>.Add(string key, int value) {
this.InnerDictionary.Add(key, value);
}
bool IDictionary<string, int>.ContainsKey(string key) {
return this.InnerDictionary.ContainsKey(key);
}
bool IDictionary<string, int>.Remove(string key) {
return this.InnerDictionary.Remove(key);
}
bool IDictionary<string, int>.TryGetValue(string key, out int value) {
return this.InnerDictionary.TryGetValue(key, out value);
}
int IDictionary<string, int>.this[string index] {
get {
return this.InnerDictionary[index];
}
set {
this.InnerDictionary[index] = value;
}
}
ICollection<string> IDictionary<string, int>.Keys {
get {
return this.InnerDictionary.Keys;
}
}
ICollection<int> IDictionary<string, int>.Values {
get {
return this.InnerDictionary.Values;
}
}
#endregion
#region ICollection implementation
void ICollection<KeyValuePair<string, int>>.Add(KeyValuePair<string, int> item) {
this.InnerCollection.Add(item);
}
void ICollection<KeyValuePair<string, int>>.Clear() {
this.InnerDictionary.Clear();
}
bool ICollection<KeyValuePair<string, int>>.Contains(KeyValuePair<string, int> item) {
return this.InnerCollection.Contains(item);
}
void ICollection<KeyValuePair<string, int>>.CopyTo(KeyValuePair<string, int>[] array, int arrayIndex) {
this.InnerCollection.CopyTo(array, arrayIndex);
}
bool ICollection<KeyValuePair<string, int>>.Remove(KeyValuePair<string, int> item) {
return this.InnerCollection.Remove(item);
}
int ICollection<KeyValuePair<string, int>>.Count {
get {
return this.InnerCollection.Count;
}
}
bool ICollection<KeyValuePair<string, int>>.IsReadOnly {
get {
return this.InnerCollection.IsReadOnly;
}
}
#endregion
#region IEnumerable implementation
IEnumerator<KeyValuePair<string, int>> IEnumerable<KeyValuePair<string, int>>.GetEnumerator() {
return this.InnerCollection.GetEnumerator();
}
#endregion
#region IEnumerable implementation
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return (this as IEnumerable).GetEnumerator();
}
#endregion
}
}
不幸的是,您不能将 reallyADict
转换为 Dictionary<string,T>
之类的东西,因为您需要特定的类型。
而 Manfred 的评论是使用像
这样的通用方法
public IEnumerable<T> SomeMethod<T>(Dictionary<string, T> dict)
也是我的方法。但是你说你真的只有字典 object
.
所以我用反射解决了这个问题:
public IEnumerable<object> SomeMethod(object reallyADict)
{
Type genericInterface = reallyADict?.GetType().GetInterface("IDictionary`2");
PropertyInfo propKeys = genericInterface?.GetProperty("Keys");
if (propKeys?.GetMethod == null) yield break;
IEnumerable<string> keys = (IEnumerable<string>)propKeys.GetValue(reallyADict);
PropertyInfo propIndex = genericInterface.GetProperty("Item");
if (propIndex?.GetMethod == null) yield break;
foreach (string key in keys)
yield return propIndex.GetMethod.Invoke(reallyADict, new object[] { key });
}
此方法从 reallyDict
(如果有的话)中获取 Keys
属性 并将其用作 IEnumerable<string>
.
然后它遍历所有这些键并使用基础字典的索引器 属性 到 return 值。索引器 属性 的名称为 Item
。
我有一个对象的引用。我知道它符合
IDictionary<string, T>
对于某些类型 T。(它可能不符合普通 IDictionary 或 IReadyOnlyDictionary)。我所知道的关于 T 的是它从 object 派生而来。我怎样才能得到它的键,并得到一个键的值? (我可以将值作为对象而不是 T 返回。我也可以从不了解 T 是什么。)
想写却写不出来的是这样的:
public void SomeMethod(object reallyADict) { // reallyADict implements IDictionary<string, T>.
foreach (string key in reallyADict.Keys) {
object value = reallyADict[key];
// . . .
}
}
**
根据请求,下面是示例 class。
using System;
using System.Collections.Generic;
using System.Collections;
namespace My.Collections
{
public class WrappedDictionary: IDictionary<string, int>
{
public WrappedDictionary() {
this.InnerDictionary = new Dictionary<string, int>{ {"one", 1}, {"two", 2 }};
}
private Dictionary<string, int> InnerDictionary { get; set;}
private ICollection<KeyValuePair<string, int>> InnerCollection {
get {
return this.InnerDictionary;
}
}
#region IDictionary implementation
void IDictionary<string, int>.Add(string key, int value) {
this.InnerDictionary.Add(key, value);
}
bool IDictionary<string, int>.ContainsKey(string key) {
return this.InnerDictionary.ContainsKey(key);
}
bool IDictionary<string, int>.Remove(string key) {
return this.InnerDictionary.Remove(key);
}
bool IDictionary<string, int>.TryGetValue(string key, out int value) {
return this.InnerDictionary.TryGetValue(key, out value);
}
int IDictionary<string, int>.this[string index] {
get {
return this.InnerDictionary[index];
}
set {
this.InnerDictionary[index] = value;
}
}
ICollection<string> IDictionary<string, int>.Keys {
get {
return this.InnerDictionary.Keys;
}
}
ICollection<int> IDictionary<string, int>.Values {
get {
return this.InnerDictionary.Values;
}
}
#endregion
#region ICollection implementation
void ICollection<KeyValuePair<string, int>>.Add(KeyValuePair<string, int> item) {
this.InnerCollection.Add(item);
}
void ICollection<KeyValuePair<string, int>>.Clear() {
this.InnerDictionary.Clear();
}
bool ICollection<KeyValuePair<string, int>>.Contains(KeyValuePair<string, int> item) {
return this.InnerCollection.Contains(item);
}
void ICollection<KeyValuePair<string, int>>.CopyTo(KeyValuePair<string, int>[] array, int arrayIndex) {
this.InnerCollection.CopyTo(array, arrayIndex);
}
bool ICollection<KeyValuePair<string, int>>.Remove(KeyValuePair<string, int> item) {
return this.InnerCollection.Remove(item);
}
int ICollection<KeyValuePair<string, int>>.Count {
get {
return this.InnerCollection.Count;
}
}
bool ICollection<KeyValuePair<string, int>>.IsReadOnly {
get {
return this.InnerCollection.IsReadOnly;
}
}
#endregion
#region IEnumerable implementation
IEnumerator<KeyValuePair<string, int>> IEnumerable<KeyValuePair<string, int>>.GetEnumerator() {
return this.InnerCollection.GetEnumerator();
}
#endregion
#region IEnumerable implementation
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return (this as IEnumerable).GetEnumerator();
}
#endregion
}
}
不幸的是,您不能将 reallyADict
转换为 Dictionary<string,T>
之类的东西,因为您需要特定的类型。
而 Manfred 的评论是使用像
这样的通用方法public IEnumerable<T> SomeMethod<T>(Dictionary<string, T> dict)
也是我的方法。但是你说你真的只有字典 object
.
所以我用反射解决了这个问题:
public IEnumerable<object> SomeMethod(object reallyADict)
{
Type genericInterface = reallyADict?.GetType().GetInterface("IDictionary`2");
PropertyInfo propKeys = genericInterface?.GetProperty("Keys");
if (propKeys?.GetMethod == null) yield break;
IEnumerable<string> keys = (IEnumerable<string>)propKeys.GetValue(reallyADict);
PropertyInfo propIndex = genericInterface.GetProperty("Item");
if (propIndex?.GetMethod == null) yield break;
foreach (string key in keys)
yield return propIndex.GetMethod.Invoke(reallyADict, new object[] { key });
}
此方法从 reallyDict
(如果有的话)中获取 Keys
属性 并将其用作 IEnumerable<string>
.
然后它遍历所有这些键并使用基础字典的索引器 属性 到 return 值。索引器 属性 的名称为 Item
。