トップ回答者
PropertyInfo.GetValueで多次元配列の要素を指定したい

質問
回答
-
Hongliangさんも返信されていますが…
test1もtest2もプロパティとしては2次元配列ではありません。というか1次元配列でもありません。
- test1はList<int>型を扱うプロパティ
- test2はint[]型を扱うプロパティ
です。どちらもインデックス付きプロパティではなく、次元はありません。GetValue()で得られたオブジェクトに対して、改めてアクセスする必要があります。
もう少し説明すると、PropertyInfo.GetValue()は言語に依存しない中立的な実装のためにインデックス付きプロパティをサポートしますが、C#言語としては、私がサンプルとして挙げたようにインデクサーとして宣言時にはthis[ , , ]という形しかとることができません。またそのインデクサーは同じくサンプルから読み取れますがプロパティ名としては"Item"固定です。
- 回答としてマーク ashalu 2011年7月22日 2:01
すべての返信
-
その書き方で合っています。サンプルを書いて確認してみました。
class Program { static void Main(string[] args) { var sample = new Sample(); var x = 8; var y = 3; Console.WriteLine("sample[{0},{1}] = {2}", x, y, sample[x, y]); var prop = sample.GetType().GetProperty("Item"); var value = prop.GetValue(sample, new object[] { x, y }); Console.WriteLine("via PropertyInfo = {0}", value); } } public class Sample { public int this[int x, int y] { get { return x * 10 + y; } } }
そこで思ったのは、そもそもアクセスしようとしているプロパティが、2次元配列ではないということはありませんか?
なお、質問の際に、参考にしたサンプルのアドレスや、発生したエラー内容も含めてもらえると話が進みやすいです。
-
回答ありがとうございます。
回答を頂きこちらで確認したところ2次元配列であることはあったのですが、もとのソース自体に問題があったようです。
もともと以下サンプルのようにしてprivateな配列にアクセスしていたのですが、1次元配列ではなくListで実装されていたようです。
よって今回の問題の原因は配列自体にアクセスできていなかったというのが原因でした。
class Program
{
static void Main(string[] args)
{ //test1にはアクセスできるのですが、test2ではアクセスできません。
var sample = new Sample();
PropertyInfo p1 = sample.GetType().GetProperty("test1", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
var SpCollection = p1.GetValue(sample, null);
PropertyInfo pi2 = SpCollection.GetType().GetProperty("Item", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
Console.WriteLine(pi2.GetValue(SpCollection, new object[] { 1 }));
}
}public class Sample
{
private List<int> test1 { get; set; }
private int[] test2 { get; set; }public Sample()
{
test1 = new List<int>(new int[] { 1, 2, 3 });
test2 = new int[] { 4, 5, 6 };
}
}詳しく理解していないのですが配列には"Item"に変わるものがあるのかな~?と
String indexerName = ((DefaultMemberAttribute)SpCollection.GetType().GetCustomAttributes(typeof(DefaultMemberAttribute), true)[0]).MemberName;
で調べてみたのですがどうやらないようで、別の方法を考えることにしました。
質問内容の答えは頂けたので大変満足です。ありがとうございました。
-
Hongliangさんも返信されていますが…
test1もtest2もプロパティとしては2次元配列ではありません。というか1次元配列でもありません。
- test1はList<int>型を扱うプロパティ
- test2はint[]型を扱うプロパティ
です。どちらもインデックス付きプロパティではなく、次元はありません。GetValue()で得られたオブジェクトに対して、改めてアクセスする必要があります。
もう少し説明すると、PropertyInfo.GetValue()は言語に依存しない中立的な実装のためにインデックス付きプロパティをサポートしますが、C#言語としては、私がサンプルとして挙げたようにインデクサーとして宣言時にはthis[ , , ]という形しかとることができません。またそのインデクサーは同じくサンプルから読み取れますがプロパティ名としては"Item"固定です。
- 回答としてマーク ashalu 2011年7月22日 2:01
-
>>もう少し説明すると、PropertyInfo.GetValue()は言語に依存しない中立的な実装のためにインデックス付きプロパティをサポートしますが、C#言語としては、私がサンプルとして挙げたようにインデクサーとして宣言時にはthis[ , , ]という形しかとることができません。またそのインデクサーは同じくサンプルから読み取れますがプロパティ名としては"Item"固定です。
噛み砕いた解説のおかげで非常によく理解できました。ありがとうございます。
GetValue()にて得られた値に対してのアクセスも確認することができ満足しております。