2

1 レベルよりも深い場合に、文字列値のみに基づいて PropertyInfo を取得する一般的な方法はありますか。

これはおそらく単純なことだと思いますが、検索結果は検索基準と同じくらい良いものであり、目的の検索結果を取得するための適切なキーワードを明確にするのに問題があると思います.

私は次のようなことをしたいと思います (キーが直接プロパティ/1 レベルの場合、つまり key = 'firstName' の場合、これは完璧に機能します):

public static PropertyInfo (this HtmlHelper htmlHelper, string key) {

     PropertyInfo pInfo = htmlHelper.ViewData.Model.GetType().GetProperty(key);

     return pInfo;
}

PropertyInfoしかし、 Key がネストされたクラス、オブジェクト、リストなど、より複雑なものと等しい場合に、文字列のみに基づいてを返す方法はありますか...:

  • キー = "somelist[0].myproperty"
  • key = "Items[0].someotherlist[1].someproperty" (Items は次のように定義されていますList<Item> Items {get; set;}, someotherlist is defined similarly)

メソッドは、本質的に必要な (定義された) 数のレベルをドリルダウンするのに十分な汎用性がありますか?

4

2 に答える 2

1

だからここに私が思いついたものがあります...これは冗長になりつつあり、ほとんどが「思考の流れ」です

カスタムの HtmlHelperExtension があり、その中に:

 PropertyInfo[] pInfoArray = htmlHelper.ViewData.Model.GetType().GetProperties();

 PropertyInfo pInfo = GetPropertyInfo(pInfoArray, key);

このGetPropertyInfo()メソッドはkeyPropertyInfo配列を受け取り、キー部分 (正規表現を使用して文字列から配列の表示を削除するため、プロパティのみが残ります) がプロパティ名と一致するまで、プロパティを循環します。一致すると、これがループの最初のサイクルであるかどうかを判断し、そうである場合は、一致したプロパティを一時変数TypePropertyInfo変数に割り当てます。ループする keyParts が残っている場合、後続のループは以前に設定された一時変数と for ループ インデックス[i]を使用して、クラス構造を反復/ドリルダウンします。pInfoTemp変数を設定するたびpTypeTempに、次のループは中断した場所を使用できます。

    private static PropertyInfo GetPropertyInfo(PropertyInfo[] pInfoArray, string key)
    {
        PropertyInfo pInfo = null;
        string[] keyParts = key.Split('.');
        Regex arrayRgx = new Regex("\\[\\d*\\]");
        PropertyInfo pInfoTemp = null;
        Type pTypeTemp = null;

        foreach (PropertyInfo prop in pInfoArray)
        {
            string keyPartsTrimmed = arrayRgx.Replace(keyParts[0], ""); // removes '[#]' from string

            if (keyPartsTrimmed == prop.Name)   // match property name
            {

                for (int i = 0; i < keyParts.Count(); i++)
                {
                    if (i == 0) // initial item [0]
                    {
                        pTypeTemp = prop.PropertyType;  // gets [0]'s type
                        pInfoTemp = prop;               // assigns [0]'s property info
                    }
                    else
                    {
                        pInfoTemp = GetNestedPropertyInfo(pTypeTemp, arrayRgx.Replace(keyParts[i], "")); // gets [i]'s property info for return or next iteration
                        pTypeTemp = pInfoTemp.PropertyType; // gets [i]'s type for next iteration
                    }
                }

                pInfo = pInfoTemp;
                break;
            } 
        }

        return pInfo;
    }

この次のメソッドは、ネストされたプロパティ情報を取得するために前のメソッドによって呼び出されます。さらに重要なことは、passedItemType が List であるかどうかを検出することです (これがないと、List<> Type で要求されたプロパティを見つけることができないため、正しく機能しません。リスト項目のタイプが何であるかを知る必要があります。

    private static PropertyInfo GetNestedPropertyInfo(Type passedItemType, string passedProperty)
    {
        PropertyInfo pInfoOut = null;

        if (passedItemType.IsGenericType && passedItemType.GetGenericTypeDefinition() == typeof(List<>))
        {
            Type itemType = passedItemType.GetGenericArguments()[0];
            pInfoOut = itemType.GetProperty(passedProperty);
        }
        else
        {
            pInfoOut = passedItemType.GetProperty(passedProperty);
        }

        return pInfoOut;
    }

これは現在、現在の私の要件に合っています。次のプロパティ、リスト、サブクラス、リストを含むサブクラスなどでテストしました.4レベルの深さまでですが、深さに関係なく適切に機能するはずです:

  • ファーストネーム
  • 苗字
  • アイテム[1].スプロケット
  • subClass.subClassInt
  • subClass.mySubClassObj.sprocketObj
  • subClass.ItemsInMySubClass[1].sprocket
  • subClass.ItemsInMySubClass[0].mySubClassObj.widgetObj
  • subClass.ItemsInMySubClass[2].mySubClassObj.sprocketObj

誰かがより良い解決策を持っている場合、または私が持っているものに潜在的な問題がある場合は、フィードバックを歓迎します.

于 2013-08-06T23:54:31.853 に答える
0

あなたの場合の最善の方法は、その式を分割するパーサーを作成することです。

于 2013-08-04T16:13:42.627 に答える