【问题标题】:Shared library progress/status messages共享库进度/状态消息
【发布时间】:2014-06-25 17:28:26
【问题描述】:

我有一个方法可以做一些需要一段时间的事情并返回进度/状态消息。该方法曾经是我的控制台Program 类中的Main() 静态方法。后来,我决定将功能移动到一个共享库程序集中,以便新的 Web api 项目可以访问相同的功能,从而为 stdio 提供具有不同机制的不同用户界面。

什么是一个好的设计模式来替换我在移动方法中的所有Console.Writeline() 调用?

我正在考虑添加一个可观察的(字符串)集合来存储消息,然后让任何调用程序集订阅集合上的更改并实现它们自己的 ui 机制来向用户显示消息。

这是合理的还是重新发明轮子?框架中是否已经有专门构建的方法来处理这样的场景?

编辑:

感谢@astef,我这样实现了它:

public interface IMessageObserver
{
    void Notify(string message);
    void Notify(string format, params object[] args);
}

public class ConsoleMessageObserver : IMessageObserver
{
    public void Notify(string message)
    {
        Console.WriteLine(message);
    }

    public void Notify(string format, params object[] args)
    {
        Console.WriteLine(format, args);
    }
}

class Program
{
    static void Main()
    {
        Library.LongRunningMethod(new ConsoleMessageObserver());
    }
}

static class Library
{
    public static void LongRunningMethod(IMessageObserver observer)
    {
        observer.Notify("Some progress happened...");
    }
}

【问题讨论】:

  • 添加一个事件怎么样?这样主程序(或日志客户端)可以根据需要订阅事件并格式化、显示或记录状态事件。

标签: c# architecture software-design


【解决方案1】:

如果您需要有人处理您的进度消息,只需定义它:

public interface IProgressObserver
{
    void NotifyProgress(double done);
}

并使用:

public void YourLongRunningMethod(IProgressObserver progressObserver)
{
    // ...

    progressObserver.NotifyProgress(1d);
}

现在您可以更具体地确定谁将实际处理这些消息。例如:

public class ConsoleProgressObserver : IProgressObserver
{
    public void NotifyProgress(double done)
    {
        Console.WriteLine("Progress: {0:0.00}%", done * 100);
    }
}

这是在 Windows 98 系统中使用的一个 ;)

public class StuckingProgressObserver : IProgressObserver
{
    private const double stucksAfter = 0.95;

    private readonly IProgressObserver wrapee;

    public StuckingProgressObserver(IProgressObserver wrapee)
    {
        this.wrapee = wrapee;
    }

    public void NotifyProgress(double done)
    {
        if (done < stucksAfter)
        {
            wrapee.NotifyProgress(done);
        }
    }
}

【讨论】:

  • 这非常优雅并且效果很好。谢谢!我对它稍作修改,因为我对消息字符串而不是完成百分比感兴趣,但它是一种非常简单有效的模式。
【解决方案2】:

像@astef 建议的那样使用事件是个好主意,但他们的代码不是惯用的 C#。 .NET 直接支持委托,因此不需要单一方法接口。

在 C# 中,我们会定义 class ProgressChangedEventArgs : EventArgs,然后将 EventHandler&lt;ProgressChangedEventArgs&gt; ProgressChanged 添加到生成事件的类中。

事实上框架已经包含了System.ComponentModel命名空间中的那些。

【讨论】:

  • 我喜欢@astef 的解决方案主要是因为它不是基于事件的。一个方法接口实际上看起来相当优雅(对我来说),因为它只公开了我想要的功能(用observer.Notify() 替换Console.Writeline())并允许我以任何适当的方式实现UI 消息传递。我希望Console 已经是一些 UI 交互界面的实现,这样就不需要我自己的界面了。
  • @grenade 我认为以消息字符串形式发送进度的库是错误的抽象级别。在大多数情况下,库应该引发调用应用程序理解的事件,而不是应用程序仅仅通过的字符串。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 2021-03-19
相关资源
最近更新 更多