web-dev-qa-db-ja.com

オブジェクトのプロパティを辞書<string、string>に変換する簡単な方法はありますか

フォームオブジェクトにマッピングする多くのプロパティ(列)を持つデータベースオブジェクト(行)があります(asp:textbox、asp:dropdownlist etc)繰り返しやすくするために、このオブジェクトとプロパティを辞書マップに変換したいと思います。

例:

Dictionary<string, string> FD = new Dictionary<string,string>();
FD["name"] = data.name;
FD["age"] = data.age;
FD["occupation"] = data.occupation;
FD["email"] = data.email;
..........

さまざまなプロパティをすべて手動で入力せずに、これを簡単に行うにはどうすればよいですか?

注:FD辞書のインデックスは、データベースの列名と同じです。

29
Dexter

dataがオブジェクトであり、そのパブリックプロパティをディクショナリに配置すると仮定すると、次を試すことができます。

オリジナル-歴史的な理由でここ(2012)

Dictionary<string, string> FD = (from x in data.GetType().GetProperties() select x)
    .ToDictionary (x => x.Name, x => (x.GetGetMethod().Invoke (data, null) == null ? "" : x.GetGetMethod().Invoke (data, null).ToString()));

更新(2017)

Dictionary<string, string> dictionary = data.GetType().GetProperties()
    .ToDictionary(x => x.Name, x => x.GetValue(data)?.ToString() ?? "");
63
Yahia

HtmlHelperクラスを使用すると、AnonymounsオブジェクトをRouteValueDictonaryに変換できます。各値で.ToString()を使用して文字列の表現を取得できると思います。

 var linkAttributes = System.Web.Mvc.HtmlHelper.AnonymousObjectToHtmlAttributes(linkHtmlAttributes);

欠点は、これがASP.NET MVCフレームワークの一部であるということです。 .NET Reflectorを使用すると、メソッド内のコードは次のようになります。

public static RouteValueDictionary AnonymousObjectToHtmlAttributes(object htmlAttributes)
{
   RouteValueDictionary dictionary = new RouteValueDictionary();
  if (htmlAttributes != null)
  {
     foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(htmlAttributes))
     {
            dictionary.Add(descriptor.Name.Replace('_', '-'), descriptor.GetValue(htmlAttributes));
       }
 }
    return dictionary;
 }

このコードはヤヒアがあなたに与えた答えと同一であり、彼の答えはディクトリナリー<string、string>を提供することがわかります。反映したコードを使用すると、RouteValueDictionaryをDictonary <string、string>に簡単に変換できますが、Yahiaの答えは1つのライナーです。

編集-あなたの変換を行う方法になる可能性があるもののコードを追加しました:

EDIT 2-コードにヌルチェックを追加し、文字列値にString.Formatを使用しました

    public static Dictionary<string, string> ObjectToDictionary(object value)
    {
        Dictionary<string, string> dictionary = new Dictionary<string, string>();
        if (value != null)
        {
            foreach (System.ComponentModel.PropertyDescriptor descriptor in System.ComponentModel.TypeDescriptor.GetProperties(value))
            {
                if(descriptor != null && descriptor.Name != null)
                {
                     object propValue = descriptor.GetValue(value);
                     if(propValue != null)
                          dictionary.Add(descriptor.Name,String.Format("{0}",propValue));
            }
        }
        return dictionary;
    }

そして、ディクショナリからオブジェクトチェックに移動するには http://automapper.org/ このスレッドで提案されました ディクショナリを匿名オブジェクトに変換

10
Nick Bork
var myDict = myObj.ToDictionary(); //returns all public fields & properties

public static class MyExtensions
{
    public static Dictionary<string, object> ToDictionary(this object myObj)
    {
        return myObj.GetType()
            .GetProperties()
            .Select(pi => new { Name = pi.Name, Value = pi.GetValue(myObj, null) })
            .Union( 
                myObj.GetType()
                .GetFields()
                .Select(fi => new { Name = fi.Name, Value = fi.GetValue(myObj) })
             )
            .ToDictionary(ks => ks.Name, vs => vs.Value);
    }
}
9
L.B

System.ComponentModel.TypeDescriptor.GetProperties( ... )を見てください。これは、通常のデータバインディングビットの動作方法です。リフレクションを使用して、プロパティ記述子のコレクションを返します(値の取得に使用できます)。 ICustomTypeDescriptorを実装することにより、これらの記述子をperformace用にカスタマイズできます。

0
MaLio