如何将类转换为 Dictionary < string,string > ?

我可以将 Class 转换成 Dictionary < string,string > 吗?

在 Dictionary 中,我希望我的类属性是 钥匙,特别是属性的值是 价值

假设我的班级是

public class Location
{
public string city { get; set; }
public string state { get; set; }
public string country { get; set;
}

现在假设我的数据是

city = Delhi
state = Delhi
country = India

现在你可以很容易地理解我的意思了!

我想做一本字典! 那本字典应该是这样的:

Dictionary<string,string> dix = new Dictionary<string,string> ();
dix.add("property_name", "property_value");

我可以得到值! 但是我怎样才能得到属性名(不值钱) ?

我应该编写什么代码来创建它的动态? 这应该适用于我想要的每个类。

你可以把这个问题理解为:

如何从特定类获得属性列表?

现在我再一次解释我对字典的一个渴望!这个问题从我的 上一个问题的答案出现在我的脑海里! !

99388 次浏览

This is the recipe: 1 reflection, 1 LINQ-to-Objects!

 someObject.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.ToDictionary(prop => prop.Name, prop => (string)prop.GetValue(someObject, null))

Since I published this answer I've checked that many people found it useful. I invite everyone looking for this simple solution to check another Q&A where I generalized it into an extension method: Mapping object to dictionary and vice versa

Here a example with reflection without LINQ:

    Location local = new Location();
local.city = "Lisbon";
local.country = "Portugal";
local.state = "None";


PropertyInfo[] infos = local.GetType().GetProperties();


Dictionary<string,string> dix = new Dictionary<string,string> ();


foreach (PropertyInfo info in infos)
{
dix.Add(info.Name, info.GetValue(local, null).ToString());
}


foreach (string key in dix.Keys)
{
Console.WriteLine("nameProperty: {0}; value: {1}", key, dix[key]);
}


Console.Read();
protected string getExamTimeBlock(object dataItem)
{
var dt = ((System.Collections.Specialized.StringDictionary)(dataItem));


if (SPContext.Current.Web.CurrencyLocaleID == 1033) return dt["en"];
else return dt["sv"];
}

Give this a try.

This uses reflection to retrieve the object type, then all of the properties of the supplied object (PropertyInfo prop in obj.GetType().GetProperties(), see https://learn.microsoft.com/en-us/dotnet/api/system.type.getproperties?view=netcore-3.1). It then adds the property name as a key in the dictionary and, if a value exists, it adds the value, otherwise it adds null.

    public static Dictionary<string, object> ObjectToDictionary(object obj)
{
Dictionary<string, object> ret = new Dictionary<string, object>();


foreach (PropertyInfo prop in obj.GetType().GetProperties())
{
string propName = prop.Name;
var val = obj.GetType().GetProperty(propName).GetValue(obj, null);
if (val != null)
{
ret.Add(propName, val);
}
else
{
ret.Add(propName, null);
}
}


return ret;
}

I would like to add an alternative to reflection, using JToken. You will need to check the benchmark difference between the two to see which has better performance.

var location = new Location() { City = "London" };
var locationToken = JToken.FromObject(location);
var locationObject = locationObject.Value<JObject>();
var locationPropertyList = locationObject.Properties()
.Select(x => new KeyValuePair<string, string>(x.Name, x.Value.ToString()));

Note this method is best for a flat class structure.

Just a gift for someone only need a simple and flat Dictionary<String,String> not requiring hierarchy or deserialize back to an object like me 🌳

    private static readonly IDictionary<string, string> SPECIAL_FILTER_DICT = new Dictionary<string, string>
{
{ nameof(YourEntityClass.ComplexAndCostProperty), "Some display text instead"},
{ nameof(YourEntityClass.Base64Image), ""},
//...
};




public static IDictionary<string, string> AsDictionary(this object source, BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)
{
if (source == null)
return new Dictionary<string, string> {
{"",""}
};


return source.GetType().GetProperties(bindingAttr).ToDictionary
(
propInfo => propInfo.Name,
propInfo => propInfo.GetValue(source, null).GetSafeStringValue(propInfo.Name)
);
}




public static String GetSafeStringValue(this object obj, String fieldName)
{
if (obj == null)
return "";


if (obj is DateTime)
return GetStringValue((DateTime)obj);


// More specical convert...


if (SPECIAL_FILTER_DICT.ContainsKey(fieldName))
return SPECIAL_FILTER_DICT[fieldName];


// Override ToString() method if needs
return obj.ToString();
}




private static String GetStringValue(DateTime dateTime)
{
return dateTime.ToString("YOUR DATETIME FORMAT");
}

I hope this extension can be useful to someone.

public static class Ext {
public static Dictionary<string, object> ToDict<T>(this T target)
=> target is null
? new Dictionary<string, object>()
: typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public)
.ToDictionary(
x => x.Name,
x => x.GetValue(target)
);
}
public static Dictionary<string, object> ToDictionary(object model)
{
var serializedModel = JsonModelSerializer.Serialize(model);
return JsonModelSerializer.Deserialize<Dictionary<string, object>>(serializedModel);
}

I have used the above code. As simplified as possible and it works without reflection and the model could be nested and still work. (Change your code to not use Newtonsoft if you are using Json.net)