如何在C#中从字符串调用委托?

问题描述 投票:0回答:4

是否可以通过变量名称(作为字符串)调用存储在变量中的委托?我想我必须使用反射机制,但我没有得到任何结果

示例代码:

class Demo {
  public delegate int DemoDelegate();

  private static int One() {
    return 1;
  }

  private static void CallDelegate(string name) {
    // somehow get the value of the variable with the name
    // stored in "name" and call the delegate using reflection
  }

  private static void CallDelegate(string name, DemoDelegate d) {
    d();
  }

  static void main(string[] args) {
    DemoDelegate one = Demo.One;
    CallDelegate(one);
    // this works, but I want to avoid writing the name of the variable/delegate twice:
    CallDelegate("one", one);
  }

}

这可能吗?如果是的话怎么办?

c# .net string reflection delegates
4个回答
7
投票

变量几乎不存在。可靠地按字符串调用(在这种情况下)的唯一方法是将委托存储在字典中:

Dictionary<string, DemoDelegate> calls = new Dictionary<string, DemoDelegate> { {"one",one}, {"two",two} }

现在将该字典存储在某处(

通常在字段中),然后执行以下操作:

private int CallDelegate(string name) { return calls[name].Invoke(); // <==== args there if needed }
    

3
投票
是的,这是可能的,只要你使用 Linq 表达式,并且很少反思。

看看这段代码,它的功能与我认为你想要的类似:

using System; using System.Linq.Expressions; using System.Reflection; using System.Collections.Generic; namespace q6010555 { class Demo { static List<string> varNamesUsed = new List<string>(); public delegate int DemoDelegate(); private static int One() { return 1; } private static void CallDelegate(Expression<Func<DemoDelegate>> expr) { var lambda = expr as LambdaExpression; var body = lambda.Body; var field = body as MemberExpression; var name = field.Member.Name; var constant = field.Expression as ConstantExpression; var value = (DemoDelegate)((field.Member as FieldInfo).GetValue(constant.Value)); // now you have the variable name... you may use it somehow! // You could log the variable name. varNamesUsed.Add(name); value(); } static void Main(string[] args) { DemoDelegate one = Demo.One; CallDelegate(() => one); // show used variable names foreach (var item in varNamesUsed) Console.WriteLine(item); Console.ReadKey(); } } }
    

1
投票
public void Fire(string name) { FieldInfo field = this.GetType().GetField(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); if (field != null) { Delegate method = field.GetValue(this) as Delegate; if (method != null) { method.Method.Invoke(method.Target, new object[0]); } } }

显然限制了您使用参数化委托。


0
投票
您无法真正访问另一个堆栈框架中的变量(尽管我认为可以在

StackFrame

 类周围使用黑客技术)。相反,如果您想以类似反射的方式调用广义委托,您将需要传递 
Delegate
 对象并使用 
DynamicInvoke
 等方法。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.