タイトルの通り。
以下が基本ヘルパークラス。
// MIT license // Copyright (C) 2018 mntone. All right reserved. using System; using System.Runtime.CompilerServices; using System.Threading; namespace Mntone.YourProduct.Core.Extensions { public interface IAwaitable { bool IsCompleted { get; } Action OnCompleted { get; } void ContinueWith(Action action); } public interface IAwaitable<T> : IAwaitable { T Result { get; } } public sealed class AwaitableHelper { private readonly IAwaitable _awaitable; public bool IsCompleted { get; private set; } public Action OnCompleted { get; private set; } public AwaitableHelper(IAwaitable awaitable) { _awaitable = awaitable; } public void SetCompleted() { IsCompleted = true; OnCompleted?.Invoke(); } public void ContinueWith(Action action) { OnCompleted = action; if (_awaitable.IsCompleted && action != null) action(); } } public static class IAwaitableExtensions { public class Awaiter<T> : INotifyCompletion { private static readonly SendOrPostCallback _postCallback = state => ((Action)state)(); private readonly IAwaitable<T> _target = null; public Awaiter(IAwaitable<T> target) => _target = target; public void OnCompleted(Action continuation) { var context = SynchronizationContext.Current; _target.ContinueWith(() => { context.Post(_postCallback, continuation); }); } public bool IsCompleted => _target.IsCompleted; public T GetResult() => _target.Result; } public static Awaiter<T> GetAwaiter<T>(this IAwaitable<T> awaitable) { return new Awaiter<T>(awaitable); } } }
使い方: iOS の Delegate ベースクラスを継承したものに IAwaitable
まずは Delegate 側のサンプル
private class YourDelegate : YourDelegateBase, IAwaitable<bool> { private readonly AwaitableHelper _awaitableHelper; public bool Result { get; private set; } public YourDelegate() : base() { _awaitableHelper = new AwaitableHelper(this); } public override void OverrideMethods(...) { // 処理を入れる。終わったら Result に変数を格納し,Helper の Completed を set。 Result = true; _awaitableHelper.SetCompleted(); } #region Helper Methods public bool IsCompleted => _awaitableHelper.IsCompleted; public Action OnCompleted => _awaitableHelper.OnCompleted; public void ContinueWith(Action action) => _awaitableHelper.ContinueWith(action); #endregion }
public async Task<bool> SampleAsync() { var requestTask = new YourDelegate(); request.Delegate = requestTask; var result = await requestTask; return result; }
これにより,delegate を awaitable にすることにより外部実装は簡便化可能となる。もちろん,EAP パターンや Rx での実装可能だし,選択肢はこれだけじゃないが。