Mapowanie obiektu do słownika i odwrotnie
Czy Jest jakiś elegancki szybki sposób na mapowanie obiektu do słownika i vice versa?
Przykład:
IDictionary<string,object> a = new Dictionary<string,object>();
a["Id"]=1;
a["Name"]="Ahmad";
// .....
Staje się
SomeClass b = new SomeClass();
b.Id=1;
b.Name="Ahmad";
// ..........
10 answers
Używając pewnych odbić i generyków w dwóch metodach rozszerzeń, możesz to osiągnąć.
Racja, inni zrobili w większości to samo rozwiązanie, ale to wykorzystuje mniej odbicia, które jest bardziej wydajne i bardziej czytelne:
public static class ObjectExtensions
{
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)
{
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();
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-01 10:24:55
Wydaje się, że refleksja tylko tutaj pomaga.. Zrobiłem mały przykład konwersji obiektu do słownika i vise versa:
[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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-18 12:13:36
Gorąco polecam Castle DictionaryAdapter , jeden z najlepiej strzeżonych sekretów tego projektu. Wystarczy tylko zdefiniować interfejs z właściwościami, które chcesz, a w jednej linii kodu adapter wygeneruje implementację, utworzy instancję i zsynchronizuje jej wartości ze słownikiem, który przekazujesz. Używam go do wpisywania moich AppSettings w projekcie www:
var appSettings =
new DictionaryAdapterFactory().GetAdapter<IAppSettings>(ConfigurationManager.AppSettings);
Zauważ, że nie musiałem tworzyć klasy, która implementuje iappsettings - adapter to robi w locie. Ponadto, chociaż w tym przypadku tylko czytam, teoretycznie gdybym ustawiał wartości właściwości w appSettings, adapter utrzymywałby słownik bazowy w synchronizacji z tymi zmianami.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-04 15:27:39
Odbicie może przenieść obiekt do słownika poprzez iterację nad właściwościami.
Aby przejść w drugą stronę, będziesz musiał użyć dynamicznego ExpandoObject (który w rzeczywistości już dziedziczy z IDictionary, a więc zrobił to za Ciebie) w C#, chyba że możesz wywnioskować Typ ze zbioru wpisów w słowniku.
Więc, jeśli jesteś w. NET 4.0 land, użyj ExpandoObject, inaczej masz dużo pracy do zrobienia...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-09 11:18:58
Myślę, że powinieneś użyć refleksji. Coś takiego:
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;
}
Pobiera słownik i zapętla go i ustawia wartości. Powinieneś to poprawić, ale to jakiś początek. Powinieneś nazywać to tak:
SomeClass someClass = ConvertDictionaryTo<SomeClass>(a);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-09 12:21:28
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;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-09 12:01:01
Bazując na odpowiedzi Matíasa Fidemraizera, oto wersja, która obsługuje wiązanie z właściwościami obiektu innymi niż łańcuchy.
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)
);
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-27 19:14:29
Konwertuj najpierw słownik na ciąg JSON za pomocą Newtonsoft.
var json = JsonConvert.SerializeObject(advancedSettingsDictionary, Newtonsoft.Json.Formatting.Indented);
Następnie deserializuj łańcuch JSON do obiektu
var myobject = JsonConvert.DeserializeObject<AOCAdvancedSettings>(json);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-12 12:14:07
Jeśli używasz Asp.Net MVC, to spójrz na:
public static RouteValueDictionary AnonymousObjectToHtmlAttributes(object htmlAttributes);
Która jest statyczną metodą publiczną w systemie.Www.Mvc.Klasa HtmlHelper.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-20 13:23:54
public Dictionary<string, object> ToDictionary<T>(string key, T value)
{
try
{
var payload = new Dictionary<string, object>
{
{ key, value }
};
} catch (Exception e)
{
return null;
}
}
public T FromDictionary<T>(Dictionary<string, object> payload, string key)
{
try
{
JObject jObject = (JObject) payload[key];
T t = jObject.ToObject<T>();
return (t);
}
catch(Exception e) {
return default(T);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-28 10:30:10