using System; using System.Runtime.CompilerServices; using System.Security; namespace MagicOnion.CompilerServices { public struct AsyncUnaryResultMethodBuilder { private AsyncTaskMethodBuilder methodBuilder; private T result; private bool haveResult; private bool useBuilder; public static AsyncUnaryResultMethodBuilder Create() { return new AsyncUnaryResultMethodBuilder() { methodBuilder = AsyncTaskMethodBuilder.Create() }; } public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { methodBuilder.Start(ref stateMachine); // will provide the right ExecutionContext semantics } public void SetStateMachine(IAsyncStateMachine stateMachine) { methodBuilder.SetStateMachine(stateMachine); } public void SetResult(T result) { if (useBuilder) { methodBuilder.SetResult(result); } else { this.result = result; haveResult = true; } } public void SetException(Exception exception) { methodBuilder.SetException(exception); } public UnaryResult Task { get { if (haveResult) { return new UnaryResult(result); } else { useBuilder = true; return new UnaryResult(methodBuilder.Task); } } } public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { useBuilder = true; methodBuilder.AwaitOnCompleted(ref awaiter, ref stateMachine); } [SecuritySafeCritical] public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { useBuilder = true; methodBuilder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine); } } }