使用 async/await 初始化方法继承

Inheritance with async/await initialization methods

我的 class 有需要初始化的属性。因为我不想传递部分构造的对象,并且构造函数不能't/shouldn 异步,所以我一直在使用 here 描述的工厂模式,所以我的 class看起来像这样:

public class BaseClass
{
    public PropType AsyncProp1 { get; set; }

    public static async Task<BaseClass> CreateObject()
    {
        var baseClass = new BaseClass()
        {
            AsyncProp1 = await GetProp1Async()
        };
        return baseClass;
    }
}

到目前为止,该模式对我很有用,但现在我需要实现其他 classes,它们将扩展 BaseClass 并具有其他需要在使用其对象之前初始化的异步属性。

我最初的计划是简单地重写 CreateObject() 方法,但是不能创建静态方法 virtual/override。然后我决定隐藏基 class 中的 CreateObject() 方法,并在派生 class 中有一个新的 CreateObject() 方法,如下所示:

public class DerivedClass : BaseClass
{
    public PropType AsyncProp2 { get; set; }

    public static new async Task<DerivedClass> CreateObject()
    {
        var derivedClass = new DerivedClass()
        {
            AsyncProp1 = await GetProp1Async(),
            AsyncProp2 = await GetProp2Async(AsyncProp1) // can't do that - AsyncProp1 is not static
        };
        return derivedClass;
    }
}

不用说,对于每个派生 class 我都需要重写继承属性的初始化。仅此一点就违背了整个继承概念,但最糟糕的是派生 classes 中的一些新异步属性依赖于基础 class 中的旧异步属性,但我不能只需在 CreateObject() 方法中调用它们,因为它们不是静态属性。

有什么方法可以改进我目前所拥有的,解决这个 Catch22 问题,并实现上述目标吗?

[编辑]

只是为了提供一点上下文,我不想依赖在我的 classes 之外调用的初始化方法的原因是我可能无法控制创建对象和调用此类的代码初始化方法。这就是为什么我宁愿 return 将“准备好使用”的对象返回给调用者。

我认为您应该阅读 Stephen Cleary 的 very next post,指出让您的异步初始化对象具有一个公开 public 非异步 属性 的 API 是矛盾的](AsyncProp1)。这相当于想要一个 async 属性.

您可以重新设计此对象的接口,以便它的任何方法也是 async 并让这些方法在内部确保它已初始化(等待 InitAsync如有必要)。 ...如果防止滥用是您的主要目标。