C # Store funciona em um dictionary

Como faço para criar um dictionary onde posso armazenar funções?

Obrigado.

Eu tenho cerca de 30 + funções que podem ser executadas pelo usuário. Eu quero poder executar a function desta maneira:

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(); } } } 

No entanto, a assinatura da function nem sempre é a mesma, tendo, portanto, uma quantidade diferente de argumentos.

Como isso:

 Dictionary> 

Isso permite armazenar funções que usam um parâmetro de string e retornam booleano.

 dico[5] = foo => foo == "Bar"; 

Ou se a function não for anônima:

 dico[5] = Foo; 

onde Foo é definido assim:

 public bool Foo(string bar) { ... } 

ATUALIZAR:

Depois de ver sua atualização, parece que você não sabe de antemão a assinatura da function que gostaria de invocar. No .net, a fim de invocar uma function que você precisa para passar todos os argumentos e se você não sabe o que os argumentos vão ser a única maneira de conseguir isso é através da reflection.

E aqui está outra alternativa:

 class Program { static void Main() { // store var dico = new Dictionary(); dico[1] = new Func(Func1); dico[2] = new Func(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; } } 

Com essa abordagem, você ainda precisa saber o número e o tipo de parâmetros que precisam ser passados ​​para cada function no índice correspondente do dictionary ou você receberá um erro de execução. E se suas funções não tiverem valores de retorno, use System.Action<> vez de System.Func<> .

No entanto, a assinatura da function nem sempre é a mesma, tendo, portanto, uma quantidade diferente de argumentos.

Vamos começar com algumas funções definidas assim:

 private object Function1() { return null; } private object Function2(object arg1) { return null; } private object Function3(object arg1, object arg3) { return null; } 

Você realmente tem duas opções viáveis ​​à sua disposição:

1) Mantenha a segurança de tipo fazendo com que os clientes chamem sua function diretamente.

Esta é provavelmente a melhor solução, a menos que você tenha boas razões para romper com esse modelo.

Quando você fala sobre querer interceptar chamadas de function, parece-me que você está tentando reinventar funções virtuais. Há um monte de maneiras para obter esse tipo de funcionalidade, como herdar de uma class base e sobrepor suas funções.

Parece-me que você quer uma class que é mais um wrapper do que uma instância derivada de uma class base, então faça algo assim:

 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) mapeie a input de suas funções para uma interface comum.

Isso pode funcionar se todas as suas funções estiverem relacionadas. Por exemplo, se você está escrevendo um jogo, e todas as funções fazem algo em alguma parte do inventário do jogador ou jogador. Você acabaria com algo assim:

 class Interceptor { private object function1() { return null; } private object function2(object arg1) { return null; } private object function3(object arg1, object arg3) { return null; } Dictionary> functions; public Interceptor() { functions = new Dictionary>(); 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 func = functions[key]; return func(state); } } 

Por que não usar a lista params object[] list para parâmetros de método e fazer alguma validação dentro de seus methods (ou lógica de chamada), isso permitirá um número variável de parâmetros.

Espero que isso ajude. De que língua você vem?

 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("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> _dictionary = new Dictionary>(); public void Register(string command, Func function) { _dictionary.Add(command, args => function(args)); } public void Register(string command, Action function) { _dictionary.Add(command, args => { function.Invoke(args); return null; } ); } public T Intercept(string command, params object[] args) { return (T)_dictionary[command].Invoke(args); } public void Intercept(string command, params object[] args) { _dictionary[command].Invoke(args); } } 

O cenário a seguir permitiria usar um dictionary de elementos para enviar como parâmetros de input e obter o mesmo que os parâmetros de saída.

Primeiro adicione a seguinte linha no topo:

 using TFunc = System.Func, System.Collections.Generic.IDictionary>; 

Em seguida, dentro de sua turma, defina o dictionary da seguinte maneira:

  private Dictionary actions = new Dictionary(){ {"getmultipledata", (input) => { //DO WORKING HERE return null; } }, {"runproc", (input) => { //DO WORKING HERE return null; } } }; 

Isso permitiria que você executasse essas funções anônimas com uma syntax semelhante a esta:

 var output = actions["runproc"](inputparam); 

Defina o dictionary e inclua a referência da function como o valor, usando System.Action como o tipo:

 using System.Collections; using System.Collections.Generic; public class Actions { public Dictionary myActions = new Dictionary(); public Actions() { myActions ["myKey"] = TheFunction; } public void TheFunction() { // your logic here } } 

Em seguida, invoque-o com:

 Actions.myActions["myKey"]();