【问题标题】:Assign method to private delegate without breaking the current assignment在不破坏当前分配的情况下将方法分配给私有委托
【发布时间】:2018-11-21 20:28:28
【问题描述】:

我想使用某个班级的私人委托,但不会破坏当前的分配。 我能否以某种方式确保我的更改(通过反射完成)不会断开 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();
    }
}

感谢您的帮助

【问题讨论】:

    标签: c# delegates system.reflection propertyinfo methodinfo


    【解决方案1】:

    您必须通过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);
    

    【讨论】:

    • 是的,太好了!即使 Inform == null 也有效。非常感谢@pfx
    • 你知道如何扩展它,以便可以向 MyMethod 方法传递一个附加参数(原始委托中不存在的参数,但在执行 Delegate.Combine 期间已知) .所以 Inform 仍然会调用 WriteToDebug(字符串信息),还会调用 MyMethod(字符串 msg,字符串 EXTRA_PARAMETER)。 EXTRA_PARAMETER 将在@pfx 建议的代码中的某处提供。但是在哪里以及如何做呢?
    • EXTRA_PARAMETER 可以在使用适当的重载时转移:docs.microsoft.com/en-us/dotnet/api/…
    猜你喜欢
    • 2010-10-26
    • 2023-04-10
    • 2013-12-25
    • 1970-01-01
    • 1970-01-01
    • 2015-06-30
    • 2019-02-23
    • 2023-03-03
    相关资源
    最近更新 更多