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


73

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

在Dictionary中,我希望将类属性作为,将特定属性的作为value

假设我的课是

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

我可以得到价值!但是,如何获取属性名称(而不是value)?

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

您可以将这个问题理解为:

如何获取特定类的属性列表?

现在,我再次解释我对词典的渴望之一!从上一个问题的答案中我突然想到了这个问题


你能试着改写这个问题吗?我不知道您要达到什么目标。
ilivewithian 2012年

拼盘!我想要特定类的所有变量名称!这可能吗 ?
Chintan

@NoOne我已经回答了您,但您需要进一步了解OOP。您在谈论属性。类级别的“变量”称为字段。重要的是要用它的名字来称呼一切,因为理解您比现在要容易!;)
MatíasFidemraizer 2012年

@MatíasFidemraizer对不起!我的错误是我应该使用我编辑过的“属性”!
Chintan 2012年

@Chintan我不知道您打算在什么地方使用类的字典,请注意,与您的类相反,在该类中“ Country”可以是type的属性,Countrycity是type的属性string,在词典中,您必须指定最基本的您将要存储的类型(很可能是object),这会使您的生活更加艰难。
Tomer W

Answers:


190

这就是配方:1个反射,1个LINQ到对象!

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

自从我发布此答案以来,我检查了很多人认为它有用。我邀请寻找这种简单解决方案的所有人检查另一个问答,在此我将其概括为扩展方法:将对象映射到字典,反之亦然


如果看到“ GenericEqualityComparer”之类的“固有”属性,而不是我明确声明的属性,该怎么办?我试过了BindingFlags.DeclaredOnly
drzaus 2012年

UPDATE没关系-我发现使用这种反射的方法(本身在对象扩展中)最终以转换后的结果调用了自己,因此我的扩展在对象上调用,然后在结果字典中调用。
drzaus 2012年

2
当我尝试此操作时,它返回Dictionary <string,object>而不是Dictionary <string,string>,因此不满足OP。
蒂姆·威廉姆斯

1
@TimWilliams谢谢,我已经解决了该问题;-)
马蒂亚斯Fidemraizer

1
@TimWilliams您是否错过了转换为字符串的操作?
哈奇·摩尔

20

这是一个不带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();

这为我节省了至少一天的工作时间。非常感谢,如果可以的话,我会两次投票赞成您!
Kibitz503

2

我想使用JToken为反射添加一种替代方法。您将需要检查两者之间的基准差异,以查看哪个具有更好的性能。

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

请注意,此方法最适合平面类结构。


var locationObject = locationObject.Value<JObject>();
jon_darkstar

这是一个更紧凑的版本:var props = JToken.FromObject(query) .Value<JObject>() .Properties() .ToDictionary(k => k.Name, v => $"{v.Value}");
Makotosan,

0
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"];
}

一个解释将是有条理的。
彼得·莫滕森

0

someone给某人的礼物只需要一个简单而扁平的东西,Dictionary<String,String> 不需要层次结构或反序列化回像我这样的对象🌳

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

0

我希望此扩展名对某人有用。

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

它可以工作,但是我认为这是否是一种扩展方法,可以抽象化逻辑,其语法被“糖”语言过度压缩和遮盖。在这样的情况下,我将逻辑保留为更冗长的格式,因为它更易于阅读。
奥利弗

一个解释将是有条理的。
彼得·莫滕森

0

试试看。

这将使用反射来检索对象类型,然后使用所提供对象的所有属性(PropertyInfo prop in obj.GetType().GetProperties(),请参见https://docs.microsoft.com/zh-cn/dotnet/api/system.type.getproperties?view=netcore-3.1)。然后,它将属性名称添加为字典中的键,如果存在值,则添加该值,否则添加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;
    }

一个解释将是有条理的。
彼得·莫滕森

将修改答案。
joelc
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.