在 .NET Standard 上实现异步 return 类型

Implementing async return Types on .NET Standard

大家好,我正在尝试使用 .NetCore 框架的 AsyncMethodBuilderAttribute 创建自己的 Task-Like 类型。
到目前为止,在 .Net Core 中,我的自定义 Type 有效,它可以是 awaited 并且我可以 return 它作为 async [MyTypeName]<T> MyMethod() 而不是 Task
但是在 .NetStandard 2.0 中该属性不存在,我试图实现它:
我用该属性装饰了我的可等待类型,但它仍然不允许我使用它:"The return type of an async method must be void,Task,Task<T>"

到目前为止,我可以在 .Net Core 中使用类似的东西并且它有效!!

public async Task WrapperMethod(){
   int result=await GetIntAsync();
}
public async Errand<int> GetIntAsync()
{
  await Task.Delay(1000);
  return 3;
}

属性:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false, AllowMultiple = false)]
    public sealed class AsyncMethodBuilderAttribute : Attribute {
        //
        // Parameters:
        //   builderType:
        public AsyncMethodBuilderAttribute(Type builderType) {
            this.BuilderType = builderType;
        }

        //
        public Type BuilderType { get; }
    }


下面是自定义类型的实现和async method builderawaiter在这种情况下并不重要,但如果需要我可以提供源代码。

我的Task-喜欢类型

[AsyncMethodBuilder(typeof(Builder))]
    public partial class Errand {

        private readonly Builder mbuilder;
        public Errand() {
        }
        internal Errand(Builder methodBuilder) => this.mbuilder = methodBuilder;

        private readonly HashSet<Awaiter> awaiters = new HashSet<Awaiter>();

        protected bool isCompleted = false;

        public Awaiter GetAwaiter() {

            Awaiter result = new Awaiter(this);
            this.awaiters.Add(result);
            return result;
        }

    }

自定义 AsyncMethodBuilder 实现:

public partial class Builder {

            #region " Compiler integration "

            public static Builder Create() {
                return new Builder();
            }

            protected IAsyncStateMachine myStateMachine;

            public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine {
                this.myStateMachine = stateMachine;
                this.errand = new Errand(this);
                stateMachine.MoveNext();
            }


            public void SetException(Exception ex) {

            }

            public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine machine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine {

                var foo = machine as IAsyncStateMachine;
                awaiter.OnCompleted(() => { foo.MoveNext(); });
            }
            public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine machine)where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine {

                IAsyncStateMachine asyncMachine = machine as IAsyncStateMachine;
                awaiter.OnCompleted(() => asyncMachine.MoveNext());

            }

            private Errand errand;
            public Errand Task { get { return this.errand; } }


            public void SetStateMachine(IAsyncStateMachine stateMachine) {

            }
            public void SetResult() {

            }

            #endregion


            //  internal void AddAwaiter(Awaiter awaiter) => this.awaiters.Add(awaiter);

        }

我还应该添加什么才能在 .Net Standard 中工作?

属性的源文件在哪里并不重要,但它确实需要有正确的命名空间声明:

namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false, AllowMultiple = false)]
    public sealed class AsyncMethodBuilderAttribute : Attribute
    {
        public AsyncMethodBuilderAttribute(Type builderType) =>
            BuilderType = builderType;
        public Type BuilderType { get; }
    }
}