2011-12-19 19 views
2

これはあまりにも不可能と思われる場合、plsは投票しません:)私は今まで私はいくつかの結果を得るために関数のパラメータとしてプロパティを渡すことができますか?プロパティとしてパラメータを渡すことは可能ですか?

たとえば、

void delete_button_click() 
{ 
    foreach (DataGridViewRow row in dgvRecords.SelectedRows) 
     dgvRecords.Rows.Remove(row); 
} 

そして唯一の違いはSelectedRowsRowsあるので、

void delete_all_button click() 
{ 
    foreach (DataGridViewRow row in dgvRecords.Rows) 
     dgvRecords.Rows.Remove(row); 
} 

は、私は1つの機能で上記の2つのコードを書くことができたとします。このような何か:。

void button_click (/*DataGridView property rows*/) 
{ 
    foreach (DataGridViewRow row in dgvRecords.rows) 
     dgvRecords.Rows.Remove(row); 
} 

そして

{ 
    button_click(DataGridView.Rows); 
    //and 
    button_click(DataGridView.SelectedRows); 
} 

別例えばそれを呼び出す、

decimal GetAmount1(User usr) 
{ 
    decimal sum = 0; 
    foreach (DataGridViewRow row in dgvRecords.Rows) 
    { 
     Tuple<User, User, Notification, Acknowledgment> tup = (Tuple<User, User, Notification, Acknowledgment>)row.Tag; 
     if (tup.Item1 == usr) 
      sum += tup.Item4.Sum; 

    } 
    return sum; 
} 

decimal GetAmount2(User usr) 
{ 
    decimal sum = 0; 
    foreach (DataGridViewRow row in dgvRecords.Rows) 
    { 
     Tuple<User, User, Notification, Acknowledgment> tup = (Tuple<User, User, Notification, Acknowledgment>)row.Tag; 
     if (tup.Item2 == usr) 
      sum += tup.Item4.Sum; 

    } 
    return sum; 
} 

上記のコードでの唯一の違いは、単に財産です。だから、これは提供されています:

decimal GetAmount(User usr, Tuple<User, User, Notification, Acknowledgment>.Property Item) 
{ 
    decimal sum = 0; 
    foreach (DataGridViewRow row in dgvRecords.Rows) 
    { 
     Tuple<User, User, Notification, Acknowledgment> tup = (Tuple<User, User, Notification, Acknowledgment>)row.Tag; 
     if (tup.Item == usr) 
      sum += tup.Item4.Sum; 

    } 
    return sum; 
} 

およびコール:

{ 
    GetAmount(usr, Tuple<User, User, Notification, Acknowledgment>.Item1) 
    //and 
    GetAmount(usr, Tuple<User, User, Notification, Acknowledgment>.Item2) 
} 

+0

[クラスのプロパティをメソッドのパラメータとして渡すにはどうすればいいですか?](http://stackoverflow.com/questions/1178574/how-can-i-pass-a-property-of -a-a-method-of-a-methodのメソッド) – nawfal

答えて

3

あなたの最初の例では、普通のパラメータを使用して解決することができるされている。

行を削除するメソッドのシグネチャは次のようになります

void RemoveRows (IList rows) 
{ 
    foreach (var row in rows) 
     dgvRecords.Rows.Remove(row); 
} 

としてそれを呼び出す:

RemoveRows (DataGridView.Rows); 
//or 
RemoveRows (DataGridView.SelectedRows); 

2番目の例では、選択するプロパティを定義できるようにするFunc<T, TResult>を使用する必要があります。

だからあなたGetAmount()方法のsigantureは次のようになります。

decimal GetAmount(User usr, Func<Tuple<User, User, Notification, Acknowledgment>, User> selector) 
{ 
    decimal sum = 0; 
    foreach (DataGridViewRow row in dgvRecords.Rows) 
    { 
     Tuple<User, User, Notification, Acknowledgment> tup = (Tuple<User, User, Notification, Acknowledgment>)row.Tag; 
     if (selector(tup) == usr) 
      sum += tup.Item4.Sum; 

    } 
    return sum; 
} 

、あなたはそれを呼び出します:あなたが反射でこれを行うことができ

GetAmount(usr, tuple => tuple.Item1); 
//or 
GetAmount(usr, tuple => tuple.Item1); 
+0

すごい!まさに私が望んでいたもの。私はどんなクレイジーな質問を投稿することを恥じてはいけないと思う、解決策はまだ言語で存在するかもしれない:) – nawfal

+1

まったく。私の提案は、最も簡単なことを最初に考えることです、頻繁に行く正しい方法です:) –

+0

はい:)............ – nawfal

1

最初の問題を解決するための投影は実際には必要ありませんが、プロパティを選択したいという引数のために、プロジェクタを渡して呼び出し元がプロパティを選択できるようにしますメソッドの最初のセット、あなたが行うことができます。

void DeleteRows(DataGridView dgv, Func<DataGridView, IEnumerable> projection) 
    { 
     foreach (DataGridViewRow row in projection(dgv)) 
      dgv.Rows.Remove(row); 
    } 

または、代わりにジェネリックを使用して:

void DeleteRows<TCollection>(DataGridView dgv, Func<DataGridView, TCollection> projection) where TCollection : IEnumerable 
    { 
     foreach (DataGridViewRow row in projection(dgv)) 
      dgv.Rows.Remove(row); 
    } 

次にあなたが好きそれを呼び出すことができます。

// delete all rows 
    DeleteRows(dgvRecords, d => d.Rows); 

    // delete only selected rows 
    DeleteRows(dgvRecords, d => d.SelectedRows); 

あなたが動的プロパティに渡したいどのような場合には、つまり、その代わりにオブジェクトを受け取り、必要なプロパティを返すFunc<...>を渡します。これは、呼び出し元がデータを照会する投影を指定できるようにすることによって、LINQがそのような汎用アルゴリズムを作成する方法と非常に似ています。

もちろん、publicの代理人を招待するメソッドがある場合は、それらを呼び出す前にnullでないことを確認してください。あなたのコントロール下にあるメソッドがprivateの場合、すべての呼び出しを制御するとそれほど大きな問題にはなりません。

UPDATE例2の場合:

decimal GetAmount(User usr, Func<Tuple<User, User, Notification, Acknowledgement>, User> projection) 
{ 
    decimal sum = 0; 
    foreach (DataGridViewRow row in dgvRecords.Rows) 
    { 
     Tuple<User, User, Notification, Acknowledgment> tup = (Tuple<User, User, Notification, Acknowledgment>)row.Tag; 
     if (projection(tup) == usr) 
      sum += tup.Item4.Sum; 

    } 
    return sum; 
} 

およびコール:

GetAmount(user, t => t.Item1); 

それとも

GetAmount(user, t => t.Item2); 

1が大きいためTuple少し醜いですが、まだ動作していること。

+0

これはすばらしいことです。私の質問の2番目の例と同様に、どのようなコードになりますか?私はちょっと違うと思う。 – nawfal

+0

ありがとう。あなたが最初に答えを出したので、私はこれを答えにしておこう。 – nawfal

+0

これは動作しません。私は最初の例を意味します。理由は 'DataGridViewRowCollection'と' DataGridViewSelectedRowCollection'が異なっています – nawfal

1

が、私はそれをお勧めしません。再び

int someFunction(Element instance, string propertyName) 
    { 
     MethodInfo prop = typeof(Element).GetProperty(propertyName).GetGetMethod(); 
     if (prop.ReturnType != typeof(int)) 
     { 
      throw new Exception("Type of property does not match expected type of int"); 
     } 
     return (int)prop.Invoke(instance, null); 
    } 

が、私はあなたが上記よりも良い理由があった場合を除き、このような何かをやってお勧めしません。ここでのプロパティ「ゲッター」を取得し、それを扱うの例があります。このようなことをする場合は、毎回それを再作成する必要がないように、MethodInfoオブジェクトをキャッシュするのを頑張ってください。

0

これは@Alastair Pittsメソッドですが、コードを少し変更して機能させています。

void RemoveRows (IEnumerable rows) 
{ 
    foreach (DataGridViewRow row in rows) 
     dgvRecords.Rows.Remove(row); 
} 

そして、私はIEnumerableを<にしようとした

RemoveRows ((IEnumerable)dgvRecords.Rows); 
//or 
RemoveRows ((IEnumerable)dgvRecords.SelectedRows); 

それを呼び出す>アラステアが指摘したが、それは動作しwouldntのよう。非ジェネリックをジェネリックにキャストすることはできません。 IEnumerableはSystem.Collections名前空間にあり、IEnumerable <のようなSystem.Collections.Generic名前空間にはありません。それにもかかわらず、私は彼を答えとしてマークしています。

関連する問題