c# - 使用长时间运行的构造函数设计对象

标签 c# .net design-patterns .net-3.5

我有一个类旨在为在我的应用程序中多次使用的某些特定文件提供对某些元数据的快速访问。不幸的是,一些元数据只能通过长时间运行的方法调用来提取。

我有另一个类为长时间运行的方法提供异步包装器(可能需要 5 分钟或更长时间,具体取决于文件的大小),但我正在尝试弄清楚如何调用此异步方法以及是否调用它将其放入构造函数中是合适的,或者是否有针对这种情况的更好的设计模式。

这里有一些伪代码来尝试说明我的问题:

public class MetaData
{
    public string Data1 { get; private set; }
    public string Data2 { get; private set; }

    public MetaData(String filepath)
    {
        var extractor = new ExtractMetaData(filepath);  //create instance of class that fetches the metadata

        this.Data1 = extractor.GetData1(); // short running method

        extractor.Data2Received += Data2Received;  
        extractor.GetData2Async();  // long running method, called with via async method

    }        

    private void Data2Received(object sender, MetaDataEventArgs args)
    {
        this.Data2 = args.Data;  // finally set Data2 property
    }
}

class ExtractMetaData
{

    public event Data2ReceivedEventHandler Data2Received;

    public ExtractMetaData (string filePath) { }

    public String GetData1();  // very fast method to get Data1
    public void GetData2Async();  // very slow method to get Data2

}

我想弄清楚的是是否有更好的方法来实现这一点?

现在使用我的代码,几乎不需要等待构建 MetaData,但是如果有人试图在 之前访问 MetaData.Data2 属性>GetData2Async() 方法返回并触发 Data2Received 事件,它们将获得一个 null 响应。但是如果他们在返回后调用 if,它将包含正确的信息。由于确实没有办法通知用户此方法已完成,我担心这会变成糟糕的用户体验,因为他们不必等待构造函数,而是必须等待所有属性设置。

最佳答案

首先,你说没有办法通知用户得到Data2完全的。这不是真的,您可以使用多种方式通知用户,例如事件或 Task .

但我认为您实际上应该重组您的类(class)。你说得到 Data2需要很长时间,这很可能意味着它使用了大量资源。因此,我认为您甚至不应该尝试初始化 Data2除非你必须。你怎么知道的?用户将不得不告诉你。理想情况下,如果用户不想要 Data2 ,他甚至不应该能够访问它,这意味着拆分 MetaData分为两类:类似于BasicMetaDataExtendedMetaData , 它继承自 BasicMetaData .

ExtendedMetaData , 你可以通过某种方式通知用户初始化已完成(很可能使用事件),或者你可以让构造函数等待初始化完成(你可以使用 Monitor.Wait()Monitor.Pulse() 来做到这一点) .

就我个人而言,我认为最好的选择是如果您有一个返回 Task<ExtendedMetaData> 的静态工厂方法。 .这样,用户可以同步(使用 Result )或异步(使用可用的 ContinueWith()await )等待结果。这在 .Net 4.5 中特别有用(因为 await ),而且在 .Net 4.0 中也是如此。不幸的是,您问题上的标签表明您使用的是 .Net 3.5,它没有 Task。 .如果可能,我建议您升级。

关于c# - 使用长时间运行的构造函数设计对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14533054/

相关文章:

c# - 通过样式 block 解析 Open XML 文档

C#自增运算符(++)问题:Why am i getting wrong output?

c# - "An expression tree may not contain an assignment operator"在 Select 子句中使用聚合

c# - 为什么 User.Identity 不包含 ClaimsTypes 的完整列表?

c# - Controller 中的MVC渲染部分脚本

c# - Moq - 是否可以在不使用 It.IsAny 的情况下设置模拟

c++ - C++ 中的工厂模式——这样做正确吗?

c# - 内联 if 和接口(interface)(多态性)

java - 将派生类的所有 setter 放置到 util 类是一个好的设计吗?

ruby-on-rails - 建立多人游戏网站