【问题标题】:Store reference to method with unknown signature in C#在 C# 中存储对具有未知签名的方法的引用
【发布时间】:2014-02-27 04:36:30
【问题描述】:

我看过一些帖子,其中包含有关如何执行此操作的答案。答案都依赖于在字典中放置一个动作。然而,我遇到的问题是我需要将带有未知签名的动作传递到一个方法中,而不是在字典中。

我有使用以下方法的现有代码。我想添加一个重载,以便保持与现有代码的兼容性。

    // Collection of notification observers.
    private static Dictionary<string, List<NotificationObserver>> _Observers = new Dictionary<string, List<NotificationObserver>>();
    public static SynchronizationContext Context { get; set; }

    public static void RegisterObserver(object observer, string notification, Action<object, Dictionary<string, object>> action)
    {
        // We only register valid objects.
        if (string.IsNullOrWhiteSpace(notification) || action == null || observer == null) return;

        // Create a new NotificationObserver object.
        // Currently you provide it a reference to the observer. This is not used anywhere; there are plans to use this.
        var registeredObserver = new NotificationObserver(observer, action);

        // Make sure the notification has already been registered.
        // If not, we add the notification to the dictionary, then add the observer.
        if (_Observers.ContainsKey(notification))
            _Observers[notification].Add(registeredObserver);
        else
        {
            var observerList = new List<NotificationObserver>();
            observerList.Add(registeredObserver);
            _Observers.Add(notification, observerList);
        }
    }

    public static void PostNotification(object sender, string notification, Dictionary<string, object> userData = null)
    {
        // Make sure the notification exists.
        if (_Observers.ContainsKey(notification))
        {
            // Loop through each objects in the collection and invoke their methods.
            foreach (NotificationObserver observer in _Observers[notification].Where(obs => obs != null))
            {
                if (Context == null)
                    observer.Action(sender, userData);
                else
                {
                    Context.Send((state) => observer.Action(sender, userData), null);
                }
            }

            // Clean ourself up.
            Task.Run(new Action(() =>
            {
                PurgeNullObservers();
            }));
        }
    }

通知观察者

internal sealed class NotificationObserver
{
    internal NotificationObserver(object observer, Action<object, Dictionary<string, object>> action)
    {
        this.Observer = observer;
        this.Action = action;
    }

    internal object Observer { get; private set; }
    internal Action<object, Dictionary<string, object>> Action { get; private set; }

}

我想做的是在我的代码库中执行以下操作:

NotificationManager.RegisterObserver(this.SomeProperty, "SomeString", this.SomeProperty.DoStuff);
NotificationManager.RegisterObserver(this.Logger, "LogInfo", this.Logger.LogInfo);

本质上,我想为我无法访问源代码并且无法添加与我预先确定的操作签名匹配的方法的第 3 方库对象提供支持。对于大量不同的签名变化,我也不想要 30 次重载。

任何人都知道完成此任务的体面方法吗?如果我必须修改我的 RegisterObserver 和 NotificationObserver 我可以,但我希望这样做,而不必修改现有的方法签名,只需添加一个重载。

提前致谢!

【问题讨论】:

    标签: c# delegates action observer-pattern observable


    【解决方案1】:

    为什么在构造 RegisterObserver 调用时不直接使用 lambda 表达式?

    NotificationManager.RegisterObserver(this.ThirdParty, 
        "ThirdPartyData", 
        (i,j) => 
            {
                 // call the third party method
                 this.ThirdParty.ThirdPartyMethod(null, false, i);
                 // other custom logic here using j (the action dictionary)
            });
    

    只要您拥有“调整”第三方调用以与您现有的签名兼容所需的信息,就没有问题。您会在 lambda 表达式创建的闭包中自动捕获所有此类信息。

    【讨论】:

    • 谢谢,我没有考虑过在这个庄园里做。这非常有意义,并且完全按照我的需要工作。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-13
    • 1970-01-01
    • 1970-01-01
    • 2020-05-07
    • 2020-02-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多