How to convert object to Dictionary<TKey, TValue> in C#? - c#

How do I convert a dynamic object to a Dictionary<TKey, TValue> in C# What can I do?
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
}
}

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 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.

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.

Another option is to use NewtonSoft.JSON.
var dictionary = JObject.FromObject(anObject).ToObject<Dictionary<string, object>>();

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));
}

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;
}

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();

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;
}

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);

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));
}

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;
}

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;

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>();

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;
}

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));

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]);
}

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
}
}

object parsedData = se.Deserialize(reader);
System.Collections.IEnumerable stksEnum = parsedData as System.Collections.IEnumerable;
then will be able to enumerate it!

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;
}

Related

Generic search implementation in EF Core

I'm trying to implement a generic search method which can be used with all entities of DB.
public static object HandleSearch(object objList, string searchText)
{
Dictionary<string, object> ht = null;
List<Dictionary<string, object>> returnList = new List<Dictionary<string, object>>();
var a = objList as ICollection;
object data = null;
Type tp = null;
foreach (object obj in a)
{
ht = (Dictionary<string, object>)obj;
foreach (string key in ht.Keys)
{
data = ht[key];
tp = data.GetType();
if (tp == typeof(DateTime))
{
if (((DateTime)data).ToString("dd/MM/yyyy HH:mm:ss").Contains(searchText))
{
returnList.Add(ht);
break;
}
else if (data.ToString().ToLower().Contains(searchText.ToLower()))
{
returnList.Add(ht);
break;
}
}
}
}
return returnList;
}
I should call this as
var x = _service.GetAll(eo);
var c = GeaUtility.HandleSearch(x, "29/02");
When I try it gives me "unable to cast from List to List<Dictionary<string, object>>.
How can I solve? Any ideas?

Converting object to Dictionary<PropertyName, Value>

I have a use case, where I have to show any List of objects List<T> objects as a table. So, I have implemented a function, which prepares the data in usable format:
public static Dictionary<Guid, Dictionary<string, object>> PrepareList<T>(List<T> Items, List<string> RelevantProperties)
{
var res = new Dictionary<Guid, Dictionary<string, object>>();
var propDicSplitted = new Dictionary<string, List<string>>();
foreach (string relevantProperty in RelevantProperties)
{
if (relevantProperty.Contains("."))
{
var split = relevantProperty.Split('.');
if(!propDicSplitted.ContainsKey(split[0]))
{
propDicSplitted.Add(split[0], new List<string>());
}
propDicSplitted[split[0]].Add(relevantProperty);
}
}
foreach (T item in Items)
{
var itemPropDic = item.ToDictionary();
var itemId = (Guid)itemPropDic["ID"];
if (!res.ContainsKey(itemId))
{
res.Add(itemId, new Dictionary<string, object>());
}
foreach(string relevantProperty in RelevantProperties)
{
if (itemPropDic.ContainsKey(relevantProperty)) {
res[itemId].Add(relevantProperty, itemPropDic[relevantProperty]);
}
}
foreach(string subObjectName in propDicSplitted.Keys)
{
foreach (string relevantSubProperty in propDicSplitted[subObjectName])
{
res[itemId].Add(relevantSubProperty, GetNestedPropertyValue(itemPropDic, relevantSubProperty.Split('.')));
}
}
}
return res;
}
private static object GetNestedPropertyValue(IDictionary<string, object> Obj, string[] PropertiesPath)
{
if (PropertiesPath.Length == 1)
return Obj[PropertiesPath[0]];
return GetNestedPropertyValue(Obj[PropertiesPath[0]].ToDictionary(), PropertiesPath.Skip(1).ToArray());
}
where, List<T> items is the list of items to be shown in table and List<string> RelevantProperties are the property names, which are relevant for the table. These can be nested via '.' (eg. when the Orders object has a Customer object as a property and I need to show the customer name, then it will be possible to add value to RelevantProperties as "Customer.Name", which then will be extracted).
The .ToDictionary() method is extended to provide the access to the properties as in dictionary:
public static IDictionary<string, object> ToDictionary(this object source, bool ignoreComplexTypes = false)
{
return source.ToDictionary<object>(ignoreComplexTypes);
}
public static IDictionary<string, T> ToDictionary<T>(this object source, bool ignoreComplexTypes)
{
if (source == null)
throw new ArgumentNullException("source", "Unable to convert object to a dictionary. The source object is null.");
var dictionary = new Dictionary<string, T>();
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(source))
AddPropertyToDictionary<T>(property, source, dictionary, ignoreComplexTypes);
return dictionary;
}
private static void AddPropertyToDictionary<T>(PropertyDescriptor property, object source, Dictionary<string, T> dictionary, bool ignoreComplexTypes)
{
object value = property.GetValue(source);
if (IsOfType<T>(value) && !(ignoreComplexTypes))
dictionary.Add(property.Name, (T)value);
}
private static bool IsOfType<T>(object value)
{
return value is T;
}
However, the problem is that the function PrepareList<T>() is too slow and it takes 2 minutes for a list with 10000 items and 8 relevant properties. I need a hint on how to optimize this. Any suggestions are appreciated.

Can I cast generic type to Dictionary<,> in C#?

I have programm settings in some dictionary collections.
And I need to update default settings (src dictionary) by settings from config file (dst dictionary).
So, I write a generic extension method which doesn't work for dictionary inside dictionary:
public static class DictionaryExtensions
{
public static void Update<T, U>(this Dictionary<T, U> src, Dictionary<T, U> dst)
{
// Update values by keys
var keys = src.Select(x => x.Key).ToArray();
foreach (var key in keys)
if (dst.ContainsKey(key))
{
if (typeof(U).GetGenericTypeDefinition() == typeof(Dictionary<,>))
{ // Error in recursively calling:
var d1 = src[key] as Dictionary<object, object>; // d1 is null, but it is Dictionary<,>
var d2 = dst[key] as Dictionary<object, object>; // d2 is null, but it is Dictionary<,>
d1.Update(d2); // How can I call it?
}
else
src[key] = dst[key];
}
// Append not exist values
keys = dst.Select(x => x.Key).ToArray();
foreach (var key in keys)
if (!src.ContainsKey(key))
src.Add(key, dst[key]);
}
}
Can I cast class U to unknown type of Dictionary<,> and then call Update() method recursively?
Use IDictionay , Not use generic Type , Possible can do that ,
I have not tried
public static class DictionaryExtensions
{
public static void Update(this IDictionary src, IDictionary dst)
{
foreach (object srcKey in src.Keys)
{
foreach (object dstKey in dst.Keys)
{
if (dst.Contains(srcKey))
{
IDictionary d1 = src[srcKey] as IDictionary;
IDictionary d2 = dst[srcKey] as IDictionary;
if (d1 != null && d2 != null)
{
d1.Update(d2);
}
else
src[srcKey] = dst[srcKey];
}
}
}
foreach (object dstKey in dst.Keys)
if (!src.Contains(dstKey))
src.Add(dstKey, dst[dstKey]);
}
}
And Use like this.
Dictionary<object, object> a = new Dictionary<object, object>();
Dictionary<object, object> b = new Dictionary<object, object>();
a.Update(b);
Thanks to TimChang, now my code is:
public static class DictionaryExtensions
{
public static void Update(this IDictionary src, IDictionary dst)
{
foreach (var key in dst.Keys)
if (src.Contains(key))
{
if (src[key] is IDictionary a &&
dst[key] is IDictionary b)
a.Update(b);
else
src[key] = dst[key];
}
else
{
src.Add(key, dst[key]);
}
}
}

Linq - How to query Dictionary<int,object>

I want to be able to query and sort a Dictionary<int, MyObj> by any of the properties inside MyObj.
class MyObj
{
public string Symbol { get; set; }
public string Name { get; set; }
public int AtomicNumber { get; set; }
public int Id { get; set; }
public string toString()
{
return Symbol + " " + Name + " " + AtomicNumber + " " + Id;
}
}
class Program
{
private static void AddToDictionary(Dictionary<int, MyObj> elements,
string symbol, string name, int atomicNumber, int id)
{
MyObj theElement = new MyObj();
theElement.Symbol = symbol;
theElement.Name = name;
theElement.AtomicNumber = atomicNumber;
theElement.Id = id;
elements.Add(key: theElement.Id, value: theElement);
}
private static Dictionary<int, MyObj> BuildDictionary()
{
var elements = new Dictionary<int, MyObj>();
AddToDictionary(elements, "K", "Potassium", 19, 0);
AddToDictionary(elements, "Ca", "Calcium", 20, 1);
AddToDictionary(elements, "Sc", "Scandium", 21, 2);
AddToDictionary(elements, "Ti", "Titanium", 22, 3);
return elements;
}
static List<T> GetListOfProperty<T>(Dictionary<int, MyObj> colBlobs, string property)
{
Type t = typeof(MyObj);
PropertyInfo prop = t.GetProperty(property);
if (prop == null)
{
// throw new Exception(string.Format("Property {0} not found", f.Name.ToLower()));
Console.WriteLine(string.Format("Property {0} not found", property));
return new List<T>();
}
//still need to fix this
return colBlobs.Values
.Select(blob => (T)prop.GetValue(blob))
.OrderBy(x => x)
.ToList();
}
static SortedDictionary<int, MyObj> GetListOfProperty2<T>(Dictionary<int, MyObj> colBlobs, string property)
{
// CODE?
return sortedDict;
}
static void Main(string[] args)
{
Dictionary<int, MyObj> myColl = BuildDictionary();
var res = GetListOfProperty<string>(myColl, "Name");
foreach (var rr in res)
Console.WriteLine(rr.ToString());
//outputs : Which is only one property, the one selected
//--------
//Calcium
//Potassium
//Scandium
//Titanium
var res2 = GetListOfProperty2<string>(myColl, "Name");
//want to output the whole dictionary
//<1, {"Ca", "Calcium", 20,1}
//<0, {"K", "Potassium", 19, 0}
//<2, {"Sc", "Scandium", 21, 2}
//<3, {"Ti", "Titanium", 22, 3}
}
}
Since it seems to be that it is unclear what I want. I added example output. I am pretty sure there is no way to make this question more clear.
The problem with SortedDictionary is that it can only be sorted by Key, so you'll have to use OrderBy() in some way:
public static IOrderedEnumerable<KeyValuePair<K, T>> SortByMember<K, T>(this Dictionary<K, T> data, string memberName)
{
Type type = typeof(T);
MemberInfo info = type.GetProperty(memberName) ?? type.GetField(memberName) as MemberInfo;
Func<KeyValuePair<K, T>, object> getter = kvp => kvp.Key;
if (info is PropertyInfo pi)
getter = kvp => pi.GetValue(kvp.Value);
else if (info is FieldInfo fi)
getter = kvp => fi.GetValue(kvp.Value);
return data.OrderBy(getter);
}
This can handle both properties and fields, and if the member name is invalid, it defaults to sorting by key.
You can change that to not sort if member name is invalid by changing the return value:
public static IEnumerable<KeyValuePair<K, T>> SortByMember<K, T>(this Dictionary<K, T> data, string memberName)
{
Type type = typeof(T);
MemberInfo info = type.GetProperty(memberName) ?? type.GetField(memberName) as MemberInfo;
if (info == null) return data;
Func<KeyValuePair<K, T>, object> getter = null;
if (info is PropertyInfo pi)
getter = kvp => pi.GetValue(kvp.Value);
else if (info is FieldInfo fi)
getter = kvp => fi.GetValue(kvp.Value);
return data.OrderBy(getter);
}
IMO it is wrong to return an empty dictionary if it fails to find the member. Alternatively you can throw an exception.
Use case:
Dictionary<int, MyObj> myColl = BuildDictionary();
var res = myColl.SortByMember("Name");
foreach (var rr in res)
Console.WriteLine(rr.Value);
To achieve your goal you can use expression tree to build a compiled lambda and then use this lambda in the Linq OrderBy() method:
public static class ExpressionHelper
{
public static Func<T, object> GetMemberExpressionFunc<T>(string memberName)
{
var parameter = Expression.Parameter(typeof(T));
Expression source = Expression.PropertyOrField(parameter, memberName);
Expression conversion = Expression.Convert(source, typeof(object));
return Expression.Lambda<Func<T, object>>(conversion, parameter).Compile();
}
}
static void Main(string[] args)
{
Dictionary<int, MyObj> myColl = BuildDictionary();
string property = "AtomicNumber"; // or whatever property you want your dictionary ordered by
var func = ExpressionHelper.GetMemberExpressionFunc<MyObj>(property);
var ordered = myColl.OrderBy(x => func(x.Value));
}

How to handle a generic dictionary whose types are unknown and don't matter?

If 'value' is an incoming generic dictionary whose types are unknown/don't matter, how do I take its entries and put them into a target dictionary of type IDictionary<object, object> ?
if(type == typeof(IDictionary<,>))
{
// this doesn't compile
// value is passed into the method as object and must be cast
IDictionary<,> sourceDictionary = (IDictionary<,>)value;
IDictionary<object,object> targetDictionary = new Dictionary<object,object>();
// this doesn't compile
foreach (KeyValuePair<,> sourcePair in sourceDictionary)
{
targetDictionary.Insert(sourcePair.Key, sourcePair.Value);
}
return targetDictionary;
}
EDIT:
Thanks for the responses so far.
The problem here is that the argument to Copy is only known as type 'object'. For example:
public void CopyCaller(object obj)
{
if(obj.GetType() == typeof(IDictionary<,>)
Copy(dictObj); // this doesn't compile
}
Make your method generic as well and then you'll be able to do what you're doing. You won't have to change your usage pattern since the compiler will be able to infer generic types from input types.
public IDictionary<object, object> Copy(IDictionary<TKey, TValue> source)
{
IDictionary<object,object> targetDictionary = new Dictionary<object,object>();
foreach (KeyValuePair<TKey, TValue> sourcePair in sourceDictionary)
{
targetDictionary.Insert(sourcePair.Key, sourcePair.Value);
}
return targetDictionary;
}
If you don't really need to convert it from IDictionary<TKey, TValue> to IDictionary<object, object> then you can use the copy constuctor of Dictionary<TKey, TValue> which accepts another dictionary as input and copies all values--just like you're doing now.
You can exploit the fact that generic dictionaries implement the IDictionary interface.
public static Dictionary<object, object> CreateCopy(IDictionary source)
{
var copy = new Dictionary<object, object>(source.Count);
foreach (DictionaryEntry entry in source)
{
copy.Add(entry.Key, entry.Value);
}
return copy;
}
Usage example:
var source = new Dictionary<int, string>() { { 1, "Foo" }, { 2, "Bar" }, };
var copy = CreateCopy(source);
Console.WriteLine(String.Join(", ", copy.Values));
Output:
Foo, Bar
Here is a method (don't leave it as static, unless you need it to be, I wrote it in a quick console app) that basically converts a Dictionary of any type to an object/object dictionary.
private static Dictionary<object,object> DeTypeDictionary<T,U>(Dictionary<T,U> inputDictionary)
{
Dictionary<object, object> returnDictionary = new Dictionary<object, object>();
foreach(T key in inputDictionary.Keys)
{
if( (key is object) && (inputDictionary[key] is object))
{
returnDictionary.Add(key, inputDictionary[key]);
}
else
{
//sorry these aren't objects. they may be dynamics.
continue;
}
}
return returnDictionary;
}
...and here is how you use it...
Dictionary<string, DateTime> d = new Dictionary<string, DateTime>();
d.Add("rsgfdg", DateTime.Now);
d.Add("gfdsgd", DateTime.Now);
Dictionary<object, object> newDictionary = DeTypeDictionary<string, DateTime>(d);
So you have an object that may be a Dictionary and you want to:
Test it's a dictionary
Act on it appropriately if it is
Let's start with a generic function that does what you want if you knew the type arguments:
class Bar
{
public static void Foo<TKey, TValue>(Dictionary<TKey, TValue> input) { ... }
}
Now we'll just have to do some reflection
bool TryHandleDictionary(object o)
{
var t = o.GetType();
if (!t.IsGenericType || t.GetGenericTypeDefinition() != typeof(Dictionary<,>)) return false;
var m = typeof(Bar).GetMethod("Foo", BindingFlags.Public | BindingFlags.Static);
var m1 = m.MakeGenericMethod(t.GetGenericArguments());
m1.Invoke(null, new[] { o });
return true;
}
This may be a fix for you but you'll need .net 3.5 or greater to use the var keyword.
// this should compile
foreach (var sourcePair in sourceDictionary)
{
targetDictionary.Insert(sourcePair.Key, sourcePair.Value);
}

Categories

Resources