Saya punya beberapa metode semua dengan tanda tangan yang sama (parameter dan nilai kembali) tetapi nama yang berbeda dan internal metode berbeda. Saya ingin meneruskan nama metode untuk menjalankan ke metode lain yang akan memanggil metode lewat.
public int Method1(string)
{
... do something
return myInt;
}
public int Method2(string)
{
... do something different
return myInt;
}
public bool RunTheMethod([Method Name passed in here] myMethodName)
{
... do stuff
int i = myMethodName("My String");
... do more stuff
return true;
}
public bool Test()
{
return RunTheMethod(Method1);
}
Kode ini tidak berfungsi tetapi inilah yang saya coba lakukan. Yang tidak saya mengerti adalah bagaimana menulis kode RunTheMethod karena saya perlu mendefinisikan parameter.
Jawaban:
Anda bisa menggunakan delegasi Func di .net 3.5 sebagai parameter dalam metode RunTheMethod Anda. Delegasi Func memungkinkan Anda untuk menentukan metode yang mengambil sejumlah parameter dari jenis tertentu dan mengembalikan argumen tunggal dari jenis tertentu. Ini adalah contoh yang bisa digunakan:
sumber
Action
bukanFunc<string, int>
.Action<int,string>
terkait dengan metode yang mengambil 2 parameter (int dan string) dan mengembalikan batal.Func<double,string,int>
terkait dengan metode yang mengambil 2 parameter (double
danstring
) dan kembaliint
. Jenis yang ditentukan terakhir adalah jenis kembali. Anda dapat menggunakan delegasi ini hingga 16 parameter. Jika Anda membutuhkan lebih banyak, tuliskan delegasi Anda sendiri sebagaipublic delegate TResult Func<in T1, in T2, (as many arguments as you want), in Tn, out TResult>(T1 arg1, T2 arg2, ..., Tn argn);
. Harap perbaiki saya jika saya salah paham.Anda perlu menggunakan delegasi . Dalam hal ini semua metode Anda mengambil
string
parameter dan mengembalikanint
- ini paling mudah diwakili olehFunc<string, int>
delegasi 1 . Jadi kode Anda dapat menjadi benar dengan perubahan sesederhana ini:Para delegasi memiliki kekuatan lebih besar dari ini, harus diakui. Misalnya, dengan C # Anda dapat membuat delegasi dari ekspresi lambda , sehingga Anda dapat memanggil metode Anda dengan cara ini:
Itu akan membuat fungsi anonim seperti ini:
dan kemudian meneruskan delegasi itu ke
RunTheMethod
metode.Anda dapat menggunakan delegasi untuk berlangganan acara, eksekusi asinkron, callback - semua jenis hal. Sebaiknya baca di atasnya, terutama jika Anda ingin menggunakan LINQ. Saya memiliki artikel yang sebagian besar tentang perbedaan antara delegasi dan acara, tetapi Anda mungkin tetap menemukan manfaatnya.
1 Ini hanya berdasarkan pada
Func<T, TResult>
jenis delegasi umum dalam kerangka kerja; Anda dapat dengan mudah mendeklarasikan sendiri:dan kemudian membuat parameter menjadi tipe
MyDelegateType
gantinya.sumber
public **delegate** int MyDelegateType(string value)
?Dari contoh OP:
Anda dapat mencoba Aksi Delegasi! Dan kemudian panggil metode Anda menggunakan
Atau
Maka cukup panggil metode
sumber
InvokeMethod
RunTheMethod
Pemakaian:
sumber
Untuk berbagi solusi selengkap mungkin, saya akan berakhir dengan menghadirkan tiga cara berbeda untuk melakukan, tetapi sekarang saya akan mulai dari prinsip paling dasar.
Perkenalan singkat
Semua bahasa yang berjalan di atas CLR ( Common Language Runtime ), seperti C #, F #, dan Visual Basic, bekerja di bawah VM, yang menjalankan kode pada tingkat yang lebih tinggi daripada bahasa asli seperti C dan C ++ (yang langsung dikompilasi ke mesin kode). Oleh karena itu metode tidak berupa blok terkompilasi, tetapi mereka hanya elemen terstruktur yang diakui CLR. Dengan demikian, Anda tidak dapat berpikir untuk meneruskan metode sebagai parameter, karena metode tidak menghasilkan nilai sendiri, karena mereka bukan ekspresi! Sebaliknya, itu adalah pernyataan, yang didefinisikan dalam kode CIL yang dihasilkan. Jadi, Anda akan menghadapi konsep delegasi.
Apa itu delegasi?
Delegasi mewakili pointer ke metode. Seperti yang saya katakan di atas, metode bukan nilai, maka ada kelas khusus dalam bahasa CLR
Delegate
, yang merangkum metode apa pun.Lihatlah contoh berikut:
Tiga cara berbeda, konsep yang sama di belakang:
Cara 1
Gunakan
Delegate
kelas khusus secara langsung seperti contoh di atas. Masalah dari solusi ini adalah bahwa kode Anda akan tidak dicentang ketika Anda memberikan argumen Anda secara dinamis tanpa membatasi mereka ke jenis yang ada dalam definisi metode.Cara 2
Selain
Delegate
kelas khusus, konsep delegasi menyebar ke delegasi khusus, yang merupakan definisi metode yang didahului olehdelegate
kata kunci, dan mereka berperilaku sama seperti metode normal. Dengan demikian mereka diperiksa, sehingga Anda akan menemukan kode aman tanpa cacat.Ini sebuah contoh:
Cara 3
Atau, Anda dapat menggunakan delegasi yang telah ditentukan dalam .NET Standard:
Action
membungkusvoid
tanpa argumen.Action<T1>
mengakhirivoid
dengan satu argumen.Action<T1, T2>
membungkusvoid
dengan dua argumen.Func<TR>
membungkus fungsi denganTR
tipe kembali dan tanpa argumen.Func<T1, TR>
merangkai fungsi denganTR
tipe kembali dan dengan satu argumen.Func<T1, T2, TR>
mengakhiri fungsi denganTR
tipe kembali dan dengan dua argumen.(Solusi terakhir adalah yang paling banyak diposting orang.)
sumber
Func<T1,T2,TR>
Anda harus menggunakan
Func<string, int>
delegasi, yang mewakili fungsi mengambilstring
argumen sebagai dan mengembalikanint
:Kemudian gunakan:
sumber
Test
Metode harusreturn RunTheMethod(Method1);
Jika Anda ingin kemampuan untuk mengubah metode mana yang dipanggil saat dijalankan saya akan merekomendasikan menggunakan delegasi: http://www.codeproject.com/KB/cs/delegates_step1.aspx
Ini akan memungkinkan Anda untuk membuat objek untuk menyimpan metode untuk memanggil dan Anda bisa meneruskannya ke metode lain ketika diperlukan.
sumber
Meskipun jawaban yang diterima benar-benar benar, saya ingin memberikan metode tambahan.
Saya berakhir di sini setelah melakukan pencarian sendiri untuk solusi untuk pertanyaan serupa. Saya sedang membangun kerangka kerja yang digerakkan oleh plugin, dan sebagai bagian dari itu saya ingin orang-orang dapat menambahkan item menu ke menu aplikasi ke daftar generik tanpa mengekspos
Menu
objek yang sebenarnya karena kerangka kerja tersebut dapat digunakan pada platform lain yang tidak memilikiMenu
UI benda. Menambahkan info umum tentang menu cukup mudah, tetapi memungkinkan pengembang plugin cukup bebas untuk membuat panggilan balik ketika menu diklik terbukti menyebalkan. Sampai saya sadar bahwa saya sedang mencoba untuk menemukan kembali roda dan panggilan menu normal dan memicu panggilan balik dari acara!Jadi solusinya, sesederhana kedengarannya begitu Anda menyadarinya, menghindari saya sampai sekarang.
Cukup buat kelas terpisah untuk masing-masing metode Anda saat ini, diwarisi dari basis jika Anda harus, dan tambahkan saja pengendali acara ke masing-masing metode.
sumber
Berikut adalah contoh yang dapat membantu Anda lebih memahami cara melewatkan fungsi sebagai parameter.
Misalkan Anda memiliki halaman Induk dan Anda ingin membuka jendela sembulan anak. Di halaman induk ada kotak teks yang harus diisi berdasarkan kotak teks popup anak.
Di sini Anda perlu membuat delegasi.
Parent.cs // deklarasi delegasi delegasi publik batal FillName (String FirstName);
Sekarang buat fungsi yang akan mengisi kotak teks Anda dan fungsi harus memetakan delegasi
Sekarang pada tombol klik Anda perlu membuka jendela popup Anak.
DI konstruktor ChildPopUp Anda perlu membuat parameter 'tipe delegasi' dari halaman induk //
ChildPopUp.cs
sumber
Jika Anda ingin meneruskan Metode sebagai parameter, gunakan:
sumber
Ini adalah contoh tanpa parameter: http://en.csharp-online.net/CSharp_FAQ:_How_call_a_method_using_a_name_string
dengan params: http://www.daniweb.com/forums/thread98148.html#
Anda pada dasarnya mengirimkan array objek beserta nama metode. Anda kemudian menggunakan keduanya dengan metode Invoke.
parameter params Object []
sumber
Kelas kedua adalah Klien, yang akan menggunakan kelas penyimpanan. Ini memiliki metode Utama yang membuat instance dari PersonDB, dan ia memanggil metode Proses objek itu dengan metode yang didefinisikan dalam kelas Klien.
sumber