簡體   English   中英

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

[英]How to call delegate from string in C#?

是否可以通過變量名稱(作為字符串)調用存儲在變量中的委托? 我想我必須使用反射機制,但我沒有得到任何地方

示例代碼:

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

}

這有可能嗎? 如果是這樣的話? 如果沒有,那么我必須使用第二種形式,運氣不好

變量幾乎不存在。 可靠地逐個字符串調用(在這種情況下)的唯一方法是將委托存儲在字典中:

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
}

是的,只要您使用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();
        }
    }
}
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]);
                }
            }
        }

顯然會限制您使用參數化代理。

你無法真正訪問另一個堆棧框架中的變量(盡管我認為可以在StackFrame類中使用hackery)。 相反,如果要以類似反射的方式調用通用委托,則需要傳遞Delegate對象並使用DynamicInvoke等方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM