通过反射在C#中获取委托集合的所有具体实现

时间:2015-05-08 15:26:27

标签: c# methods reflection delegates concrete

是的,我试图让标题更小,但我不能。

我对反思非常陌生,所以我正在努力解决一个我不知道是否有可能解决的问题。

我将使用一些简单的委托示例来描述它。

public void Main() {
    var manager = new EvManager();
    var class1 = new Class1(manager);
    var class2 = new Class2(manager);

    manager.ExecuteIt(5, 12);
    /*
    This outputs:
    In Class1 -> 17
    In Class2 -> 18
    */
}

public class EvManager {
    public delegate void SumDelegate(int a, int b);
    private SumDelegate sum;

    public void AddDelegate(SumDelegate s) {
        sum += s;
    }

    public void ExecuteIt(int a, int b) {
        sum.Invoke(a, b);
    }
}

public class Class1 {
    public Class1(EvManager m) {
        m.AddDelegate(MySum);
    }

    private void MySum(int a, int b) {
        Console.Write("In Class1 -> " + (a + b));
    }
}

public class Class2 {
    public Class2(EvManager m) {
        m.AddDelegate(MyOtherSum);
    }

    private void MyOtherSum(int a, int b){
        Console.Write("In Classe2 -> " + (a + b));
    }
}

好的,这是一个例子。我想从中得到什么?我希望,通过EvManager"总和" delegate属性能够访问它调用的所有方法的具体实现。

这基本上就是我想要的:

class EvManager {
    private SumDelegate sum;
    public void ExecuteIt(int a, int b) {
        var invocationList = sum.GetInvocationList();
        foreach (var m in invocationList) {
            // m is a reference to the annonymous call.
            // Through reflection, I want to access the concrete method name.
            // In this case, the first iteration "MySum", and the second "MyOtherSum"
            // Is this possible?

            // Like...
            // var concreteMethodName = m.GetMethod().ConcreteCallerType.GetMethod(m.GetConreteMethodName());
            // Or something like that?
        }   
    }
}

希望我明白我的问题,这是在扼杀我。

4 个答案:

答案 0 :(得分:1)

Method属性包含有关实际方法的信息:

var mName = m.Method.Name;

答案 1 :(得分:1)

您可以将以下方法添加到EvManager

public void ListDelegates()
{
    foreach (var m in sum.GetInvocationList())
    {
        Console.WriteLine(m.Method.Name);
    }
}

调用它会给你你想要的东西:

MySum
MyOtherSum

Delegate课程参考上查看here

答案 2 :(得分:1)

实际上,它非常简单。使用Method属性。

检查此代码:

using System;

namespace ConsoleApplication2
{

    public class EvManager
    {
        public delegate int SumDelegate(int a, int b);
        private SumDelegate sum;

        public void AddDelegate(SumDelegate s)
        {
            sum += s;
        }

        public void ExecuteIt(int a, int b)
        {
            foreach (var m in sum.GetInvocationList())
            {
                Console.WriteLine("{0}({1}, {2}) = {3}", m.Method.Name, a, b, m.DynamicInvoke(a, b));
            }

        }
    }

    public class Class1
    {
        public Class1(EvManager m)
        {
            m.AddDelegate(FakeSum);
        }

        public int FakeSum(int a, int b)
        {
            return a - b;
        }
    }

    public class Class2
    {
        public Class2(EvManager m)
        {
            m.AddDelegate(RealSum);
        }

        public int RealSum(int a, int b)
        {
            return a + b;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var manager = new EvManager();
            var class1 = new Class1(manager);
            var class2 = new Class2(manager);

            manager.ExecuteIt(5, 12);
        }
    }
}

输出:

FakeSum(5, 12) = -7
RealSum(5, 12) = 17

答案 3 :(得分:0)

您可以通过MethodInfo delegates的{​​{3}} Property获取每个分拆Delegate的{​​{1}} class EvManager { private SumDelegate sum; public void ExecuteIt(int a, int b) { var invocationList = sum.GetInvocationList(); foreach (var m in invocationList) { var concreteMethodName = m.Method.Name; } } } 属性。

$string_1 = '4-3|5-2|9-6|7-1|2-8';
preg_match_all('/(\d+)-\d+\|?/',$string_1,$matches);
$string_2 = implode(", ", $matches[1]);