将对象映射到字典,反之亦然
是否有任何优雅的快速方法将对象映射到字典,反之亦然?
例:
IDictionary<string,object> a = new Dictionary<string,object>(); a["Id"]=1; a["Name"]="Ahmad"; // .....
变
SomeClass b = new SomeClass(); b.Id=1; b.Name="Ahmad"; // ..........
在两个方法扩展中使用一些reflection和generics可以实现这一点。
对,其他人大多采取了相同的解决scheme,但是这种方式使用的reflection更less,性能更好,方式更具可读性:
public static class ObjectExtensions { public static T ToObject<T>(this IDictionary<string, object> source) where T : class, new() { T someObject = new T(); Type someObjectType = someObject.GetType(); foreach (KeyValuePair<string, object> item in source) { someObjectType.GetProperty(item.Key).SetValue(someObject, item.Value, null); } return someObject; } public static IDictionary<string, object> AsDictionary(this object source, BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance) { return source.GetType().GetProperties(bindingAttr).ToDictionary ( propInfo => propInfo.Name, propInfo => propInfo.GetValue(source, null) ); } } class A { public string Prop1 { get; set; } public int Prop2 { get; set; } } class Program { static void Main(string[] args) { Dictionary<string, object> dictionary = new Dictionary<string, object>(); dictionary.Add("Prop1", "hello world!"); dictionary.Add("Prop2", 3893); A someObject = dictionary.ToObject<A>(); IDictionary<string, object> objectBackToDictionary = someObject.AsDictionary(); } }
我强烈推荐Castle DictionaryAdapter ,它很容易成为该项目最好保存的秘密之一。 你只需要定义一个你想要的属性的接口,在一行代码中,适配器将生成一个实现,实例化它,并将它的值与你传入的字典进行同步。我使用它强制键入我的AppSettings一个web项目:
var appSettings = new DictionaryAdapterFactory().GetAdapter<IAppSettings>(ConfigurationManager.AppSettings);
请注意,我不需要创build一个实现IAppSettings的类 – 适配器可以在运行时执行此操作。 此外,虽然在这种情况下,我只是在阅读,理论上,如果我在appSettings上设置属性值,适配器将保持底层字典与这些更改同步。 这是一个很好的教程:
http://blog.andreloker.de/post/2008/06/10/Castle-DictionaryAdapter.aspx
似乎reflection只有帮助在这里..我做了一个小的例子,将对象转换为字典,反之亦然:
[TestMethod] public void DictionaryTest() { var item = new SomeCLass { Id = "1", Name = "name1" }; IDictionary<string, object> dict = ObjectToDictionary<SomeCLass>(item); var obj = ObjectFromDictionary<SomeCLass>(dict); } private T ObjectFromDictionary<T>(IDictionary<string, object> dict) where T : class { Type type = typeof(T); T result = (T)Activator.CreateInstance(type); foreach (var item in dict) { type.GetProperty(item.Key).SetValue(result, item.Value, null); } return result; } private IDictionary<string, object> ObjectToDictionary<T>(T item) where T: class { Type myObjectType = item.GetType(); IDictionary<string, object> dict = new Dictionary<string, object>(); var indexer = new object[0]; PropertyInfo[] properties = myObjectType.GetProperties(); foreach (var info in properties) { var value = info.GetValue(item, indexer); dict.Add(info.Name, value); } return dict; }
reflection可以通过迭代属性将对象转换为字典。
换个angular度来说 ,你必须在C#中使用一个dynamic的ExpandoObject (实际上它已经从IDictionaryinheritance了,所以你已经这样做了),除非你可以从这个集合中的条目推断出这个types字典莫名其妙。
所以,如果你在.NET 4.0的土地上,使用ExpandoObject,否则你有很多工作要做…
我想你应该使用反思。 像这样的东西:
private T ConvertDictionaryTo<T>(IDictionary<string, object> dictionary) where T : new() { Type type = typeof (T); T ret = new T(); foreach (var keyValue in dictionary) { type.GetProperty(keyValue.Key).SetValue(ret, keyValue.Value, null); } return ret; }
它需要你的字典,并通过它循环,并设置值。 你应该做得更好,但这是一个开始。 你应该这样称呼它:
SomeClass someClass = ConvertDictionaryTo<SomeClass>(a);
public class SimpleObjectDictionaryMapper<TObject> { public static TObject GetObject(IDictionary<string, object> d) { PropertyInfo[] props = typeof(TObject).GetProperties(); TObject res = Activator.CreateInstance<TObject>(); for (int i = 0; i < props.Length; i++) { if (props[i].CanWrite && d.ContainsKey(props[i].Name)) { props[i].SetValue(res, d[props[i].Name], null); } } return res; } public static IDictionary<string, object> GetDictionary(TObject o) { IDictionary<string, object> res = new Dictionary<string, object>(); PropertyInfo[] props = typeof(TObject).GetProperties(); for (int i = 0; i < props.Length; i++) { if (props[i].CanRead) { res.Add(props[i].Name, props[i].GetValue(o, null)); } } return res; } }
如果你正在使用Asp.Net MVC,那么看看:
public static RouteValueDictionary AnonymousObjectToHtmlAttributes(object htmlAttributes);
这是System.Web.Mvc.HtmlHelper类的静态公共方法。
基于MatíasFidemraizer的回答,这是一个支持绑定到除string以外的对象属性的版本。
using System.Collections.Generic; using System.Linq; using System.Reflection; namespace WebOpsApi.Shared.Helpers { public static class MappingExtension { public static T ToObject<T>(this IDictionary<string, object> source) where T : class, new() { var someObject = new T(); var someObjectType = someObject.GetType(); foreach (var item in source) { var key = char.ToUpper(item.Key[0]) + item.Key.Substring(1); var targetProperty = someObjectType.GetProperty(key); if (targetProperty.PropertyType == typeof (string)) { targetProperty.SetValue(someObject, item.Value); } else { var parseMethod = targetProperty.PropertyType.GetMethod("TryParse", BindingFlags.Public | BindingFlags.Static, null, new[] {typeof (string), targetProperty.PropertyType.MakeByRefType()}, null); if (parseMethod != null) { var parameters = new[] { item.Value, null }; var success = (bool)parseMethod.Invoke(null, parameters); if (success) { targetProperty.SetValue(someObject, parameters[1]); } } } } return someObject; } public static IDictionary<string, object> AsDictionary(this object source, BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance) { return source.GetType().GetProperties(bindingAttr).ToDictionary ( propInfo => propInfo.Name, propInfo => propInfo.GetValue(source, null) ); } } }
使用Newtonsoft首先将字典转换为JSONstring。
var json = JsonConvert.SerializeObject(advancedSettingsDictionary, Newtonsoft.Json.Formatting.Indented);
然后将JSONstring反序列化到您的对象
var myobject = JsonConvert.DeserializeObject<AOCAdvancedSettings>(json);