如何在 C # 中将对象转换为 Dictionary < TKey,TValue > ?

如何在 C # 中将动态对象转换为 Dictionary<TKey, TValue>,我能做什么?

public static void MyMethod(object obj)
{
if (typeof(IDictionary).IsAssignableFrom(obj.GetType()))
{
// My object is a dictionary, casting the object:
// (Dictionary<string, string>) obj;
// causes error ...
}
else
{
// My object is not a dictionary
}
}
213698 次浏览

this should work:

for numbers, strings, date, etc.:

    public static void MyMethod(object obj)
{
if (typeof(IDictionary).IsAssignableFrom(obj.GetType()))
{
IDictionary idict = (IDictionary)obj;


Dictionary<string, string> newDict = new Dictionary<string, string>();
foreach (object key in idict.Keys)
{
newDict.Add(key.ToString(), idict[key].ToString());
}
}
else
{
// My object is not a dictionary
}
}

if your dictionary also contains some other objects:

    public static void MyMethod(object obj)
{
if (typeof(IDictionary).IsAssignableFrom(obj.GetType()))
{
IDictionary idict = (IDictionary)obj;
Dictionary<string, string> newDict = new Dictionary<string, string>();


foreach (object key in idict.Keys)
{
newDict.Add(objToString(key), objToString(idict[key]));
}
}
else
{
// My object is not a dictionary
}
}


private static string objToString(object obj)
{
string str = "";
if (obj.GetType().FullName == "System.String")
{
str = (string)obj;
}
else if (obj.GetType().FullName == "test.Testclass")
{
TestClass c = (TestClass)obj;
str = c.Info;
}
return str;
}

As I understand it, you're not sure what the keys and values are, but you want to convert them into strings?

Maybe this can work:

public static void MyMethod(object obj)
{
var iDict = obj as IDictionary;
if (iDict != null)
{
var dictStrStr = iDict.Cast<DictionaryEntry>()
.ToDictionary(de => de.Key.ToString(), de => de.Value.ToString());


// use your dictStrStr
}
else
{
// My object is not an IDictionary
}
}

Assuming key can only be a string but value can be anything try this

public static Dictionary<TKey, TValue> MyMethod<TKey, TValue>(object obj)
{
if (obj is Dictionary<TKey, TValue> stringDictionary)
{
return stringDictionary;
}


if (obj is IDictionary baseDictionary)
{
var dictionary = new Dictionary<TKey, TValue>();
foreach (DictionaryEntry keyValue in baseDictionary)
{
if (!(keyValue.Value is TValue))
{
// value is not TKey. perhaps throw an exception
return null;
}
if (!(keyValue.Key is TKey))
{
// value is not TValue. perhaps throw an exception
return null;
}


dictionary.Add((TKey)keyValue.Key, (TValue)keyValue.Value);
}
return dictionary;
}
// object is not a dictionary. perhaps throw an exception
return null;
}
    public static KeyValuePair<object, object > Cast<K, V>(this KeyValuePair<K, V> kvp)
{
return new KeyValuePair<object, object>(kvp.Key, kvp.Value);
}


public static KeyValuePair<T, V> CastFrom<T, V>(Object obj)
{
return (KeyValuePair<T, V>) obj;
}


public static KeyValuePair<object , object > CastFrom(Object obj)
{
var type = obj.GetType();
if (type.IsGenericType)
{
if (type == typeof (KeyValuePair<,>))
{
var key = type.GetProperty("Key");
var value = type.GetProperty("Value");
var keyObj = key.GetValue(obj, null);
var valueObj = value.GetValue(obj, null);
return new KeyValuePair<object, object>(keyObj, valueObj);
}
}
throw new ArgumentException(" ### -> public static KeyValuePair<object , object > CastFrom(Object obj) : Error : obj argument must be KeyValuePair<,>");
}

From the OP:

Instead of converting my whole Dictionary, i decided to keep my obj dynamic the whole time. When i access the keys and values of my Dictionary with a foreach later, i use foreach(dynamic key in obj.Keys) and convert the keys and values to strings simply.

I use this helper:

public static class ObjectToDictionaryHelper
{
public static IDictionary<string, object> ToDictionary(this object source)
{
return source.ToDictionary<object>();
}


public static IDictionary<string, T> ToDictionary<T>(this object source)
{
if (source == null)
ThrowExceptionWhenSourceArgumentIsNull();


var dictionary = new Dictionary<string, T>();
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(source))
AddPropertyToDictionary<T>(property, source, dictionary);
return dictionary;
}


private static void AddPropertyToDictionary<T>(PropertyDescriptor property, object source, Dictionary<string, T> dictionary)
{
object value = property.GetValue(source);
if (IsOfType<T>(value))
dictionary.Add(property.Name, (T)value);
}


private static bool IsOfType<T>(object value)
{
return value is T;
}


private static void ThrowExceptionWhenSourceArgumentIsNull()
{
throw new ArgumentNullException("source", "Unable to convert object to a dictionary. The source object is null.");
}
}

the usage is just to call .ToDictionary() on an object

Hope it helps.

object parsedData = se.Deserialize(reader);
System.Collections.IEnumerable stksEnum = parsedData as System.Collections.IEnumerable;

then will be able to enumerate it!

   public static void MyMethod(object obj){
Dictionary<string, string> dicEditdata = data as Dictionary<string, string>;
string abc=dicEditdata["id"].ToString();}

suppose--- if you place the cursor over the object(obj) while debugging and if you get an object with the value {['id':'ID1003']} then you can use the value as

string abc=dicEditdata["id"].ToString();

Simple way:

public IDictionary<T, V> toDictionary<T, V>(Object objAttached)
{
var dicCurrent = new Dictionary<T, V>();
foreach (DictionaryEntry dicData in (objAttached as IDictionary))
{
dicCurrent.Add((T)dicData.Key, (V)dicData.Value);
}
return dicCurrent;
}

You can create a generic extension method and then use it on the object like:

public static class Extensions
{
public static KeyValuePair<TKey, TValue> ToKeyValuePair<TKey, TValue>(this Object obj)
{
// if obj is null throws exception
Contract.Requires(obj != null);


// gets the type of the obj parameter
var type = obj.GetType();
// checks if obj is of type KeyValuePair
if (type.IsGenericType && type == typeof(KeyValuePair<TKey, TValue>))
{


return new KeyValuePair<TKey, TValue>(
(TKey)type.GetProperty("Key").GetValue(obj, null),
(TValue)type.GetProperty("Value").GetValue(obj, null)
);


}
// if obj type does not match KeyValuePair throw exception
throw new ArgumentException($"obj argument must be of type KeyValuePair<{typeof(TKey).FullName},{typeof(TValue).FullName}>");
}

and usage would be like:

KeyValuePair<string,long> kvp = obj.ToKeyValuePair<string,long>();

The above answers are all cool. I found it easy to json serialize the object and deserialize as a dictionary.

var json = JsonConvert.SerializeObject(obj);
var dictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);

I don't know how performance is effected but this is much easier to read. You could also wrap it inside a function.

public static Dictionary<string, TValue> ToDictionary<TValue>(object obj)
{
var json = JsonConvert.SerializeObject(obj);
var dictionary = JsonConvert.DeserializeObject<Dictionary<string, TValue>>(json);
return dictionary;
}

Use like so:

var obj = new { foo = 12345, boo = true };
var dictionary = ToDictionary<string>(obj);

I use this simple method:

public Dictionary<string, string> objToDict(XYZ.ObjectCollection objs) {
var dict = new Dictionary<string, string>();
foreach (KeyValuePair<string, string> each in objs){
dict.Add(each.Key, each.Value);
}
return dict;
}

This code securely works to convert Object to Dictionary (having as premise that the source object comes from a Dictionary):

    private static Dictionary<TKey, TValue> ObjectToDictionary<TKey, TValue>(object source)
{
Dictionary<TKey, TValue> result = new Dictionary<TKey, TValue>();


TKey[] keys = { };
TValue[] values = { };


bool outLoopingKeys = false, outLoopingValues = false;


foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(source))
{
object value = property.GetValue(source);
if (value is Dictionary<TKey, TValue>.KeyCollection)
{
keys = ((Dictionary<TKey, TValue>.KeyCollection)value).ToArray();
outLoopingKeys = true;
}
if (value is Dictionary<TKey, TValue>.ValueCollection)
{
values = ((Dictionary<TKey, TValue>.ValueCollection)value).ToArray();
outLoopingValues = true;
}
if(outLoopingKeys & outLoopingValues)
{
break;
}
}


for (int i = 0; i < keys.Length; i++)
{
result.Add(keys[i], values[i]);
}


return result;
}

You can use this:

Dictionary<object,object> mydic = ((IEnumerable)obj).Cast<object>().ToList().ToDictionary(px => px.GetType().GetProperty("Key").GetValue(px), pv => pv.GetType().GetProperty("Value").GetValue(pv));

If you don't mind LINQ Expressions;

public static Dictionary<string, object> ConvertFromObjectToDictionary(object arg)
{
return arg.GetType().GetProperties().ToDictionary(property => property.Name, property => property.GetValue(arg));
}

Another option is to use NewtonSoft.JSON.

var dictionary = JObject.FromObject(anObject).ToObject<Dictionary<string, object>>();

I've done something like this and works for me.

using System.ComponentModel;

var dictionary = new Dictionary<string, string>();


foreach (var propDesc in TypeDescriptor.GetProperties(Obj))
{
if (!string.IsNullOrEmpty(propDesc.GetValue(Obj)))
{
dictionary.Add(propDesc.Name, propDesc.GetValue(Obj));
}
}

Also, another alternative and innovative solution is here.

var dictionary = new System.Web.Routing.RouteValueDictionary(Obj);

This way for object array to Dictionary<string, object> List coverting

object[] a = new object[2];
var x = a.Select(f => (Dictionary<string, object>)f).ToList();

This way for single object to Dictionary<string, object> coverting

object a = new object;
var x = (Dictionary<string, object>)a;

I hope this could work :)

    //  obj = new { a = "string", b = 0, c = true };
static Dictionary<string, object> ToDictionary(object obj)
{
int i = 0;
var props = obj.GetType().GetProperties();
return props.ToDictionary(k => props[i].Name, v => props[i++].GetValue(obj));
}
    string BaseUrl = "http://www.example.com";
HttpClient client = new HttpClient { BaseAddress = new Uri(BaseUrl) };
PropertyInfo[] properties = object.GetType().GetProperties();
Dictionary<string, string> dictionary = new Dictionary<string, string>();
foreach (PropertyInfo property in properties)
{
dictionary.Add(property.Name, property.GetValue(model, null).ToString());
}
               

foreach (string key in dictionary.Keys)
{
client.DefaultRequestHeaders.Add(key, dictionary[key]);
}