C#将函数存储在Dictionary中
如何创build一个可以存储函数的字典?
谢谢。
我有大约30多个可以从用户执行的function。 我想能够这样执行function:
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(); } } }
然而,函数签名并不总是相同的,因此具有不同数量的参数。
喜欢这个:
Dictionary<int, Func<string, bool>>
这允许您存储带有string参数的函数并返回布尔值。
dico[5] = foo => foo == "Bar";
或者,如果该function不是匿名的:
dico[5] = Foo;
Foo定义如下:
public bool Foo(string bar) { ... }
更新:
看到你的更新后,似乎你不知道你想调用的函数的签名。 在.NET中,为了调用一个函数,你需要传递所有的参数,如果你不知道参数是什么,唯一的方法就是通过reflection。
还有另外一个select:
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; } }
通过这种方法,您仍然需要知道需要传递给每个函数的参数的数量和types,以及相应的字典索引,否则您将得到运行时错误。 如果你的函数没有返回值,请使用System.Action<>
来代替System.Func<>
。
然而,函数签名并不总是相同的,因此具有不同数量的参数。
我们从几个定义如下的函数开始:
private object Function1() { return null; } private object Function2(object arg1) { return null; } private object Function3(object arg1, object arg3) { return null; }
你真的有两个可行的select在你的处置:
1)通过让客户直接调用你的函数来保持types安全。
这可能是最好的解决scheme,除非你有很好的理由打破这种模式。
当你谈论要拦截函数调用时,听起来像你正在试图重新发明虚拟函数。 有许多方法可以获得这种function,例如从基类inheritance它的function。
对我来说,就像你想要一个更类似于基类的派生实例的包装类,所以做这样的事情:
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)或者将你的函数的input映射到一个通用接口。
如果你所有的function都是相关的,这可能会起作用。 例如,如果您正在编写游戏,并且所有function都会对玩家或玩家的广告资源的某些部分执行某些操作。 你最终会得到这样的结果:
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); } }
为什么不使用params object[] list
方法参数,并在你的方法(或调用逻辑)中做一些validation,它将允许可变数量的参数。
嘿,我希望这有助于。 你来自哪种语言?
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); } }
下面的场景将允许您使用元素的字典作为input参数发送,并获得相同的输出参数。
首先在顶部添加以下行:
using TFunc = System.Func<System.Collections.Generic.IDictionary<string, object>, System.Collections.Generic.IDictionary<string, object>>;
然后在你的课堂里面,定义字典如下:
private Dictionary<String, TFunc> actions = new Dictionary<String, TFunc>(){ {"getmultipledata", (input) => { //DO WORKING HERE return null; } }, {"runproc", (input) => { //DO WORKING HERE return null; } } };
这将允许您运行这些匿名函数的语法与此类似:
var output = actions["runproc"](inputparam);