- PR -

動的プロパティの取得

投稿者投稿内容
こねこばす
会議室デビュー日: 2005/12/27
投稿数: 9
投稿日時: 2006-02-01 15:07
こんにちは。いつも参考にさせていただいています。

ある自作クラスにプロパティが複数作成してあり、
プロパティ名をkeyに動的にプロパティの取得・値の反映を行いたいと思っております。
Reflectionを使用して色々試してみたのですが、
プロパティを取得することができませんでした。
もし、ご存知の方がいらっしゃいましたらご教授お願いします。

以下サンプルです。
------------------------------------------
namespace MyNamespaace
{
[Serializable]
public class MyClass
{
private int _property1;
private int _property2;

public int Property1
{
get { return _property1; }
set { _property1 = value; }
}

public int Property2
{
get { return _property2; }
set { _property2 = value; }
}

Public void SetValue(string propertyName, string propertyValue)
{
Type myType = typeof(int);
FieldInfo[] fis = myType.GetFields();

foreach(FieldInfo fi in fis)
{
if(fi.Name.Equals(propertyName))  ←ここで取得できる項目は「MaxValue・MinValue」になっています。
fi.SetValue(fi, propertyValue);
}
}

}
------------------------------------------
囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2006-02-01 15:23
引用:

Type myType = typeof(int);


int だから。

引用:

FieldInfo[] fis = myType.GetFields();


PropertyInfo info = myType.GetProperty( propertyName );

引用:

fi.SetValue(fi, propertyValue);


ん〜、設定する値まで String だとチョト無理なような…。

コード:
public void SetValue( string propertyName, int propertyValue ) 
{ 
	Type myType = GetType();
	PropertyInfo info = myType.GetProperty( propertyName );
	info.SetValue( this, propertyValue, BindingFlags.Public | BindingFlags.SetProperty, null, null, null );
} 



_________________
囚人のジレンマな日々
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-01 16:11
引用:

囚人さんの書き込み (2006-02-01 15:23) より:

ん〜、設定する値まで String だとチョト無理なような…。


ん〜、無理なの?

コード:

    public void SetValue(string propertyName, object setValue) {
        System.Type hType = this.GetType();

        System.Reflection.PropertyInfo hInfo = hType.GetProperty(
            propertyName,
            System.Reflection.BindingFlags.Public |
            System.Reflection.BindingFlags.Instance |
            System.Reflection.BindingFlags.DeclaredOnly
        );

        if (hInfo == null) {
            throw new System.ArgumentException("存在しないプロパティです。", propertyName);
        }

        if (! hInfo.CanWrite) {
            throw new System.ArgumentException("読み取り専用のプロパティです。", propertyName);
        }

        try {
            hInfo.SetValue(this, setValue, null);
        } catch (System.Exception ex) {
            throw ex;
        }
    }


相変わらず、かなり適当ですが。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2006-02-01 16:27
引用:

ん〜、無理なの?


無理っぽいですね。

じゃんぬさんの出されたコードだと、Int32 が入ってくれる可能性があるのでそのときはOK。他の型だと吹っ飛びます。(そのときはそのときで例外スローして仕舞いってのならOKです)
質問者のコードだと、String 固定なので必ず吹っ飛びます。(例のコードのプロパティが Int32 だから。Int32.Parse() すればいいけど、リフレクションしてる意味薄れますよね)
※吹っ飛ぶ → 実行時エラー。

プロパティを名前で探し出し、設定する値も文字列から得たいのかな?
プロパティの型が様々だというなら、何らかの手段を以って「設定する値の型」も得ないと駄目っぽいですね。

_________________
囚人のジレンマな日々
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-01 17:06
引用:

囚人さんの書き込み (2006-02-01 16:27) より:

無理っぽいですね。
じゃんぬさんの出されたコードだと、Int32 が入ってくれる可能性があるのでそのときはOK。


検証したコード。

コード:

    private static void MakiMakiLove() {
        Jeanne.Ini.IniFile hIniFile = new Jeanne.Ini.IniFile();

        hIniFile.FilePath     = "MakiMakiLove.ini";
        hIniFile.DefaultValue = "DefaultValue";
        hIniFile.BufferSize   = 128;

        hIniFile.SetValue("FilePath",     "FilePath は変更された");
        hIniFile.SetValue("DefaultValue", "DefaultValue は変更された");
        hIniFile.SetValue("BufferSize",   256);

        Console.WriteLine(hIniFile.FilePath);
        Console.WriteLine(hIniFile.DefaultValue);
        Console.WriteLine(hIniFile.BufferSize);
    }

コード:

    結果 :
        FilePath は変更された
        DefaultValue は変更された
        256


引用:

他の型だと吹っ飛びます。(そのときはそのときで例外スローして仕舞いってのならOKです)


そっちのことですか... orz

コンパイル解決できない手法をとっている以上、強い型意識はしないで良いという意図になるはずです。
イヤならコレクションか配列を使うべきだと思います。

# 古い話、Properties[] As Property には型はない。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-01 17:16
引用:

囚人さんの書き込み (2006-02-01 16:27) より:

プロパティの型が様々だというなら、何らかの手段を以って「設定する値の型」も得ないと駄目っぽいですね。


一応、GetSetMethod やらで GetParameters して PrameterType から取得できますが、
先の理由で、やっぱりあまり意味はないですね...

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2006-02-01 18:06
一応、ごく簡単にやってしまうのであれば…
普通(かどうかは分かりませんが)、PropertyTypeで型を調べて、
TypeDescriptorからTypeConverterを取得してごにょごにょ。
そんなことやるならプロパティもTypeDescriptorからとったほうが
いいかもしれませんが。
nanbu
大ベテラン
会議室デビュー日: 2004/08/19
投稿数: 178
投稿日時: 2006-02-01 18:51
引用:

なちゃさんの書き込み (2006-02-01 18:06) より:
一応、ごく簡単にやってしまうのであれば…
普通(かどうかは分かりませんが)、PropertyTypeで型を調べて、
TypeDescriptorからTypeConverterを取得してごにょごにょ。
そんなことやるならプロパティもTypeDescriptorからとったほうが
いいかもしれませんが。



南部です。

上記ごにょごにょをコード化するとこんなイメージです。
デザイン時以外では使ったことないですが。

コード:
private void button1_Click(object sender, System.EventArgs e)
{
  //格納するデータ
  StringDictionary propTable = new StringDictionary();
  propTable.Add("IntValue", "A");
  propTable.Add("DateValue", "2006/2/1");

  Test t = new Test();
  PropertyDescriptorCollection props = 
    System.ComponentModel.TypeDescriptor.GetProperties(t);

  foreach(PropertyDescriptor prop in props)
  {
    try
    {
      prop.SetValue(t, prop.Converter.ConvertFrom(propTable[prop.Name]));
      continue;
    }
    catch(Exception){} //例外処理割愛

    prop.ResetValue(t);
  }
  
  MessageBox.Show(t.ToString());
}

//テスト用クラス
public class Test
{
  int a;
 DateTime b;

  [DefaultValue(10)]
  public int IntValue
  {
    get { return a; }
    set { a = value; }
  }
  
  public DateTime DateValue
  {
    get { return b; }
    set { b = value; }
  }

  public override string ToString()
  {
    return string.Format("a = {0}, b={1}", a, b);
  }
}

スキルアップ/キャリアアップ(JOB@IT)