如何在C#中调用string的委托?

时间:2011-05-15 19:05:49

标签: c# .net string reflection delegates

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

示例代码:

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

}

这甚至可能吗?如果是这样的话?如果没有,那么我必须使用第二种形式,运气不好

4 个答案:

答案 0 :(得分:5)

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

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
}

答案 1 :(得分: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();
        }
    }
}

答案 2 :(得分: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]);
                }
            }
        }

显然会限制您使用参数化代理。

答案 3 :(得分:0)

你无法真正访问另一个堆栈框架中的变量(尽管我认为可以在StackFrame类周围使用hackery)。相反,如果要以类似反射的方式调用通用委托,则需要传递Delegate对象并使用DynamicInvoke之类的方法。