C# 将 Dictionary<string, AnyType> 转换为 Dictionary<string, Object>(涉及反射)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10206557/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# cast Dictionary<string, AnyType> to Dictionary<string, Object> (Involving Reflection)
提问by Ryan Sullivan
Is it possible to cast a Dictionary<string, Anything>to a consistent intermediate generic type? So I would be able to cast <string, string>, <string, bool>, <string, int>, <string, anything>all to the same type of dictionary?
是否可以将 a 强制Dictionary<string, Anything>转换为一致的中间泛型类型?所以我可以将<string, string>, <string, bool>, <string, int>,<string, anything>全部转换为相同类型的字典?
I am working on a project that is using heavy reflection and I need to be able to process DIctionary types as such:
我正在开发一个使用大量反射的项目,我需要能够像这样处理字典类型:
FieldInfo field = this.GetType().GetField(fieldName);
Dictionary<string, Object> dict = (Dictionary<string, Object>)field.GetValue(this);
The above code is what I currently have and the program always fails at the cast from field.GetValue to the generic Dictionary<string, Object>.
上面的代码是我目前所拥有的,并且程序在从 field.GetValue 到 generic 的转换时总是失败Dictionary<string, Object>。
Is there a way to do this? Or should I just figure out a different way to process these Dictionaries?
有没有办法做到这一点?或者我应该想出一种不同的方式来处理这些字典?
Any help would be greatly appreciated.
任何帮助将不胜感激。
采纳答案by Gibsnag
Following AakashM's answer, the Cast doesn't seem to play ball. You can get around it by using a little helper method though:
按照AakashM 的回答,演员似乎没有打球。不过,您可以使用一个小助手方法来解决它:
IDictionary dictionary = (IDictionary)field.GetValue(this);
Dictionary<string, object> newDictionary = CastDict(dictionary)
.ToDictionary(entry => (string)entry.Key,
entry => entry.Value);
private IEnumerable<DictionaryEntry> CastDict(IDictionary dictionary)
{
foreach (DictionaryEntry entry in dictionary)
{
yield return entry;
}
}
The duck typing in foreach is handy in this instance.
在这种情况下,在 foreach 中输入鸭子很方便。
回答by Royi Namir
Is this helping you ?
这对你有帮助吗?
Dictionary<a, b> output =
input.ToDictionary(item => item.Key, item => (SomeType)item.Value);
回答by AakashM
Even if you could find some way to express this, it would be the wrong thing to do - it's not true that a Dictionary<string, bool>isa Dictionary<string, object>, so we definitely don't want to cast. Consider that if we couldcast, we could try and put a stringin as a value, which obviously doesn't fit!
即使你能找到某种方式来表达这一点,这样做也是错误的—— aDictionary<string, bool>不是a Dictionary<string, object>,所以我们绝对不想强制转换。考虑一下,如果我们可以强制转换,我们可以尝试将 astring作为值放入,这显然不合适!
What we can do, however, is cast to the non-generic IDictionary(which all Dictionary<,>s implement), then use that to construct a newDictionary<string, object>with the same values:
然而,我们可以做的是转换为非泛型IDictionary(所有Dictionary<,>s 都实现),然后使用它来构造一个具有相同值的新对象Dictionary<string, object>:
FieldInfo field = this.GetType().GetField(fieldName);
IDictionary dictionary = (IDictionary)field.GetValue(this);
Dictionary<string, object> newDictionary =
dictionary
.Cast<dynamic>()
.ToDictionary(entry => (string)entry.Key,
entry => entry.Value);
(note that you can't use .Cast<DictionaryEntry>here for the reasons discussed here. If you're pre-C# 4, and so don't have dynamic, you'll have to do the enumeration manually, as Gibsnag's answer does)
(请注意,由于此处讨论的原因,您不能.Cast<DictionaryEntry>在此处使用。如果您使用的是 C# 4 之前的版本,因此没有使用dynamic,则必须手动进行枚举,就像Gibsnag 的回答那样)
回答by singapore saravanan
Yes It is possible to cast the FieldInfoto Dictionaryas below
是的 可以将FieldInfo转换Dictionary为如下
This is one example, I have used in my code
这是一个例子,我在我的代码中使用过
Dictionary<string, string>
GetTheDict = FilesAndPaths.GetType()
.GetFields()
.Where(f => f.Name.Equals(pLoadFile))
.Select(f => (Dictionary<string, string>)f.GetValue(FilesAndPaths))
.Single();
回答by Steztric
Consider whether casting to and from objectreally is necessary. I started down that path and stumbled across this article, before realising I could achieve what I needed through generics rather than conversion. For example;
考虑是否object真的需要来回转换。我开始沿着这条路走下去,偶然发现了这篇文章,然后才意识到我可以通过泛型而不是转换来实现我需要的东西。例如;
class DictionaryUtils<T>
{
public static T ValueOrDefault(IDictionary<string, T> dictionary, string key)
{
return dictionary.ContainsKey(key) ? dictionary[key] : default(T);
}
}
This bit of code is much cleaner and will be faster than the equivalent conversion code shown in other answers.
这段代码更简洁,并且比其他答案中显示的等效转换代码更快。
回答by alozzi
When I stumbled onto the same situation, I created the following helper:
当我偶然发现同样的情况时,我创建了以下助手:
/// <summary>
/// Casts a dictionary object to the desired Dictionary type.
/// </summary>
/// <typeparam name="TKey">The target Key type.</typeparam>
/// <typeparam name="TValue">The target value type.</typeparam>
/// <param name="dictionary">The dictionary to cast.</param>
/// <returns>A copy of the input dictionary, casted to the provided types.</returns>
private Dictionary<TKey, TValue> CastDictionary<TKey, TValue>(IDictionary dictionary)
{
// Get the dictionary's type.
var dictionaryType = typeof(Dictionary<TKey, TValue>);
// If the input is not a dictionary.
if (dictionaryType.IsAssignableFrom(typeof(Dictionary<,>)))
{
// Throw an exception.
throw new Exception("The cast to a dictionary failed: The input object is not a dictionary.");
}
// Get the generic arguments of the dictionary.
var arguments = dictionaryType.GetGenericArguments();
// If the first type of the dictionary is not a descendant of TKey.
if (!(arguments[0] is TKey || arguments[0].IsAssignableFrom(typeof(TKey)))
// Or its second type is not a descendant of TValue.
|| !(arguments[1] is TValue || arguments[1].IsAssignableFrom(typeof(TValue))))
{
// Throw an exception.
throw new Exception("The cast to a dictionary failed: The input dictionary's signature does not match <" + typeof(TKey).Name + ", " + typeof(TValue).Name + ">");
}
// Get the dictionary's default constructor.
var constructor = dictionaryType.GetConstructor(Type.EmptyTypes);
// Create a new dictionary.
var output = (Dictionary<TKey, TValue>)constructor.Invoke(null);
// Loop through the dictionary's entries.
foreach (DictionaryEntry entry in dictionary)
{
// Insert the entries.
output.Add((TKey)entry.Key, (TValue)entry.Value);
}
// Return the result.
return output;
}
Could be used in your case as follows:
可以在您的情况下使用如下:
FieldInfo field = (IDictionary)this.GetType().GetField(fieldName);
Dictionary<string, Object> dict = CastDictionary<string, Object>(field.GetValue(this));

