将方法分配给私人代表,而不中断当前分配

时间:2018-11-21 20:28:28

标签: c# delegates system.reflection propertyinfo methodinfo

我想使用某个类的私有委托,但不要破坏当前的分配。 我能以某种方式确保我的更改(通过反射完成)不会断开WriteToDebug的连接吗?

代表是私人的,“通知”是私人的

public class ExternalClass
{
    private delegate void InformDelegate(string info);//PRIVATE!
    private InformDelegate Inform { get; set; }//PRIVATE!

    public ExternalClass()
    {
        Inform = WriteToDebug;//Default method
    }

    public void Foo(string bar)
    {
        Inform?.Invoke(bar);
    }

    private void WriteToDebug(string info)
    {
        Debug.WriteLine($"Info: {info}");
    }
}

将我的方法添加到委托中并进行一些测试(需要Debug.WriteLine + MessageBox.Show)

public class MyClass
{
    public void Test(string message)
    {
        ExternalClass externalClass = new ExternalClass();
        externalClass.Foo(message);

        //Assign MyMethod to SomeClass.Inform            
        MethodInfo mi = GetType().GetMethod(nameof(MyMethod), BindingFlags.NonPublic | BindingFlags.Instance);
        PropertyInfo pi = externalClass.GetType().GetProperty("Inform", BindingFlags.NonPublic | BindingFlags.Instance);
        object del = Delegate.CreateDelegate(pi.PropertyType, this, mi);
        Type type = externalClass.GetType().GetNestedType("Inform", BindingFlags.Public | BindingFlags.NonPublic);
        pi.SetValue(externalClass, del);

        //Try Foo again
        externalClass.Foo(message);//TODO: Ensure that the call "Inform? .Invoke (bar);" triggered both methods: WriteToDebug and MyMethod.
    }

    private void MyMethod(string msg)
    {
        MessageBox.Show(msg);
    }
}

验证

internal class Program
{
    private static void Main(string[] args)
    {
        MyClass myClass = new MyClass();
        myClass.Test("Hello Word!");

        Console.ReadKey();
    }
}

感谢您的帮助

1 个答案:

答案 0 :(得分:2)

您必须通过Delegate.Combine 组合您的代表与现有的代表(此处:指向WriteToDebug)。

通过以下方式检索此已有的文件:

Delegate original = pi.GetValue(externalClass) as Delegate;

并通过以下方式合并您的新商品:

Delegate combined = Delegate.Combine(original, del);

请注意,传入的委托的顺序代表执行的顺序。

您上面的完整代码如下所示。

ExternalClass externalClass = new ExternalClass();

MethodInfo mi = GetType().GetMethod(nameof(MyMethod), BindingFlags.NonPublic | BindingFlags.Instance);
PropertyInfo pi = externalClass.GetType().GetProperty("Inform", BindingFlags.NonPublic | BindingFlags.Instance);

Delegate del = Delegate.CreateDelegate(pi.PropertyType, this, mi);

Delegate original = pi.GetValue(externalClass) as Delegate;
Delegate combined = Delegate.Combine(original, del);

pi.SetValue(externalClass, combined);

externalClass.Foo(message);