Bagaimana cara membuat Kamus tempat saya dapat menyimpan fungsi?
Terima kasih.
Saya memiliki sekitar 30+ fungsi yang dapat dijalankan dari pengguna. Saya ingin dapat menjalankan fungsi dengan cara ini:
private void functionName(arg1, arg2, arg3)
{
// code
}
dictionaryName.add("doSomething", functionName);
private void interceptCommand(string command)
{
foreach ( var cmd in dictionaryName )
{
if ( cmd.Key.Equals(command) )
{
cmd.Value.Invoke();
}
}
}
Namun, tanda tangan fungsi tidak selalu sama, sehingga memiliki jumlah argumen yang berbeda.
Jawaban:
Seperti ini:
Dictionary<int, Func<string, bool>>
Ini memungkinkan Anda untuk menyimpan fungsi yang mengambil parameter string dan mengembalikan boolean.
dico[5] = foo => foo == "Bar";
Atau jika fungsinya tidak anonim:
dico[5] = Foo;
dimana Foo didefinisikan seperti ini:
public bool Foo(string bar) { ... }
MEMPERBARUI:
Setelah melihat pembaruan Anda, tampaknya Anda tidak tahu sebelumnya tanda tangan dari fungsi yang ingin Anda panggil. Dalam .NET untuk menjalankan fungsi, Anda harus meneruskan semua argumen dan jika Anda tidak tahu argumen apa yang akan menjadi satu-satunya cara untuk mencapai ini adalah melalui refleksi.
Dan inilah alternatif lain:
class Program { static void Main() { // store var dico = new Dictionary<int, Delegate>(); dico[1] = new Func<int, int, int>(Func1); dico[2] = new Func<int, int, int, int>(Func2); // and later invoke var res = dico[1].DynamicInvoke(1, 2); Console.WriteLine(res); var res2 = dico[2].DynamicInvoke(1, 2, 3); Console.WriteLine(res2); } public static int Func1(int arg1, int arg2) { return arg1 + arg2; } public static int Func2(int arg1, int arg2, int arg3) { return arg1 + arg2 + arg3; } }
Dengan pendekatan ini, Anda masih perlu mengetahui jumlah dan jenis parameter yang perlu diteruskan ke setiap fungsi pada indeks kamus yang sesuai atau Anda akan mendapatkan error runtime. Dan jika fungsi Anda tidak memiliki nilai kembali menggunakan
System.Action<>
bukanSystem.Func<>
.sumber
Dictionary<int, Delegate>
.Mari kita mulai dengan beberapa fungsi yang didefinisikan seperti ini:
private object Function1() { return null; } private object Function2(object arg1) { return null; } private object Function3(object arg1, object arg3) { return null; }
Anda benar-benar memiliki 2 opsi yang dapat Anda gunakan:
1) Pertahankan keamanan tipe dengan meminta klien memanggil fungsi Anda secara langsung.
Ini mungkin solusi terbaik, kecuali Anda memiliki alasan yang sangat kuat untuk keluar dari model ini.
Ketika Anda berbicara tentang ingin mencegat panggilan fungsi, bagi saya kedengarannya seperti Anda mencoba menciptakan kembali fungsi virtual. Ada banyak sekali cara untuk mengeluarkan fungsionalitas semacam ini, seperti mewarisi dari kelas dasar dan menimpa fungsinya.
Kedengarannya bagi saya seperti Anda menginginkan kelas yang lebih merupakan pembungkus daripada turunan turunan dari kelas dasar, jadi lakukan sesuatu seperti ini:
public interface IMyObject { object Function1(); object Function2(object arg1); object Function3(object arg1, object arg2); } class MyObject : IMyObject { public object Function1() { return null; } public object Function2(object arg1) { return null; } public object Function3(object arg1, object arg2) { return null; } } class MyObjectInterceptor : IMyObject { readonly IMyObject MyObject; public MyObjectInterceptor() : this(new MyObject()) { } public MyObjectInterceptor(IMyObject myObject) { MyObject = myObject; } public object Function1() { Console.WriteLine("Intercepted Function1"); return MyObject.Function1(); } public object Function2(object arg1) { Console.WriteLine("Intercepted Function2"); return MyObject.Function2(arg1); } public object Function3(object arg1, object arg2) { Console.WriteLine("Intercepted Function3"); return MyObject.Function3(arg1, arg2); } }
2) ATAU petakan input fungsi Anda ke antarmuka umum.
Ini mungkin berfungsi jika semua fungsi Anda terkait. Misalnya, jika Anda sedang menulis game, dan semua fungsi melakukan sesuatu pada beberapa bagian dari pemain atau inventaris pemain. Anda akan berakhir dengan sesuatu seperti ini:
class Interceptor { private object function1() { return null; } private object function2(object arg1) { return null; } private object function3(object arg1, object arg3) { return null; } Dictionary<string, Func<State, object>> functions; public Interceptor() { functions = new Dictionary<string, Func<State, object>>(); functions.Add("function1", state => function1()); functions.Add("function2", state => function2(state.arg1, state.arg2)); functions.Add("function3", state => function3(state.arg1, state.are2, state.arg3)); } public object Invoke(string key, object state) { Func<object, object> func = functions[key]; return func(state); } }
sumber
object
seperti itu yang akan diteruskan ke Thread baru.Hei, saya harap ini membantu. Kamu berasal dari bahasa apa
internal class ForExample { void DoItLikeThis() { var provider = new StringMethodProvider(); provider.Register("doSomethingAndGetGuid", args => DoSomeActionWithStringToGetGuid((string)args[0])); provider.Register("thenUseItForSomething", args => DoSomeActionWithAGuid((Guid)args[0],(bool)args[1])); Guid guid = provider.Intercept<Guid>("doSomethingAndGetGuid", "I don't matter except if I am null"); bool isEmpty = guid == default(Guid); provider.Intercept("thenUseItForSomething", guid, isEmpty); } private void DoSomeActionWithAGuid(Guid id, bool isEmpty) { // code } private Guid DoSomeActionWithStringToGetGuid(string arg1) { if(arg1 == null) { return default(Guid); } return Guid.NewGuid(); } } public class StringMethodProvider { private readonly Dictionary<string, Func<object[], object>> _dictionary = new Dictionary<string, Func<object[], object>>(); public void Register<T>(string command, Func<object[],T> function) { _dictionary.Add(command, args => function(args)); } public void Register(string command, Action<object[]> function) { _dictionary.Add(command, args => { function.Invoke(args); return null; } ); } public T Intercept<T>(string command, params object[] args) { return (T)_dictionary[command].Invoke(args); } public void Intercept(string command, params object[] args) { _dictionary[command].Invoke(args); } }
sumber
Mengapa tidak menggunakan
params object[] list
parameter metode dan melakukan beberapa validasi di dalam metode Anda (atau logika panggilan), Ini akan memungkinkan sejumlah variabel parameter.sumber
Skenario berikut akan memungkinkan Anda menggunakan kamus elemen untuk dikirim sebagai parameter masukan dan mendapatkan parameter yang sama sebagai parameter keluaran.
Pertama tambahkan baris berikut di atas:
using TFunc = System.Func<System.Collections.Generic.IDictionary<string, object>, System.Collections.Generic.IDictionary<string, object>>;
Kemudian di dalam kelas Anda, tentukan kamus sebagai berikut:
private Dictionary<String, TFunc> actions = new Dictionary<String, TFunc>(){ {"getmultipledata", (input) => { //DO WORKING HERE return null; } }, {"runproc", (input) => { //DO WORKING HERE return null; } } };
Ini akan memungkinkan Anda untuk menjalankan fungsi anonim ini dengan sintaks yang mirip dengan ini:
var output = actions["runproc"](inputparam);
sumber
Definisikan kamus dan tambahkan referensi fungsi sebagai nilainya, menggunakan
System.Action
sebagai tipe:using System.Collections; using System.Collections.Generic; public class Actions { public Dictionary<string, System.Action> myActions = new Dictionary<string, System.Action>(); public Actions() { myActions ["myKey"] = TheFunction; } public void TheFunction() { // your logic here } }
Kemudian panggil dengan:
Actions.myActions["myKey"]();
sumber