diff --git a/src/Pose/Helpers/ShimHelper.cs b/src/Pose/Helpers/ShimHelper.cs index 0ef6cb2..379b235 100644 --- a/src/Pose/Helpers/ShimHelper.cs +++ b/src/Pose/Helpers/ShimHelper.cs @@ -65,8 +65,8 @@ public static void ValidateReplacementMethodSignature(MethodBase original, Metho .Skip(isStaticOrConstructor ? 0 : 1) .ToArray(); - if (validReturnType != shimReturnType) - throw new InvalidShimSignatureException($"Mismatched return types. Expected {validReturnType}. Got {shimReturnType}"); + // if (validReturnType != shimReturnType) + // throw new InvalidShimSignatureException($"Mismatched return types. Expected {validReturnType}. Got {shimReturnType}"); if (!isStaticOrConstructor) { diff --git a/src/Pose/PoseContext.cs b/src/Pose/PoseContext.cs index 134a4c5..2afaf85 100644 --- a/src/Pose/PoseContext.cs +++ b/src/Pose/PoseContext.cs @@ -1,11 +1,14 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Reflection.Emit; +using System.Runtime.CompilerServices; +using System.Threading; using System.Threading.Tasks; using Pose.IL; -namespace System.Runtime.CompilerServices +namespace System.Runtime.CompilerServices1 { // AsyncVoidMethodBuilder.cs in your project public class AsyncTaskMethodBuilder @@ -27,31 +30,33 @@ public void AwaitUnsafeOnCompleted( { } - + public void SetStateMachine(IAsyncStateMachine stateMachine) {} public void SetException(Exception exception) {} public Task Task => null; - + public AsyncTaskMethodBuilder() => Console.WriteLine(".ctor"); - + public static AsyncTaskMethodBuilder Create() => new AsyncTaskMethodBuilder(); - + public void SetResult() => Console.WriteLine("SetResult"); - + public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { Console.WriteLine("Start"); var methodInfos = stateMachine.GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic); - var methodRewriter = MethodRewriter.CreateRewriter(methodInfos[0], false); + var methodInfo = methodInfos[0]; + var methodRewriter = MethodRewriter.CreateRewriter(methodInfo, false); var methodBase = methodRewriter.Rewrite(); + methodBase.Invoke(this, new object[] { stateMachine }); stateMachine.MoveNext(); } - + // AwaitOnCompleted, AwaitUnsafeOnCompleted, SetException // and SetStateMachine are empty } @@ -59,9 +64,64 @@ public void Start(ref TStateMachine stateMachine) namespace Pose { + /// + /// A helper class to run Async code from a synchronize methods + /// + /// + /// Use this helper when your method isn't decorated with 'async', so you can't implement 'await' on the call to the async-method. + /// + public static class AsyncHelper + { + private static readonly TaskFactory MyTaskFactory = new TaskFactory(CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default); + + /// + /// Call this method when you need the result back from the async-method you are calling. + /// + /// + /// + /// var result = AsyncHelper.RunASync<bool>(() => IsValueTrueAsync(true)); + /// + /// + /// The type of the result. + /// The function to run. + /// The result from running . + /// If is null. + public static TResult RunASync(Func> func) + { + if (func == null) throw new ArgumentNullException(nameof(func)); + + return MyTaskFactory + .StartNew(func) + .Unwrap() + .GetAwaiter() + .GetResult(); + } + + /// + /// Call this method when you don't need any result back + /// + /// + /// + /// AsyncHelper.RunASync(() => Save(person)); + /// + /// + /// The function to run. + /// If is null. + public static void RunASync(Func func) + { + if (func == null) throw new ArgumentNullException(nameof(func)); + + MyTaskFactory + .StartNew(func) + .Unwrap() + .GetAwaiter() + .GetResult(); + } + } + public static class PoseContext { - internal static Shim[] Shims { private set; get; } + public static Shim[] Shims { set; get; } internal static Dictionary StubCache { private set; get; } public static void Isolate(Action entryPoint, params Shim[] shims) @@ -72,7 +132,9 @@ public static void Isolate(Action entryPoint, params Shim[] shims) return; } - Shims = shims; + var enumerable = new Shim[]{Shim.Replace(() => System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Create()) + .With(() => System.Runtime.CompilerServices1.AsyncTaskMethodBuilder.Create())}; + Shims = shims.Concat(enumerable).ToArray(); StubCache = new Dictionary(); var delegateType = typeof(Action<>).MakeGenericType(entryPoint.Target.GetType()); @@ -84,11 +146,11 @@ public static void Isolate(Action entryPoint, params Shim[] shims) methodInfo.CreateDelegate(delegateType).DynamicInvoke(entryPoint.Target); } - public static async Task IsolateAsync(Func entryPoint, params Shim[] shims) + public static void IsolateAsync(Func entryPoint, params Shim[] shims) { if (shims == null || shims.Length == 0) { - await entryPoint.Invoke(); + AsyncHelper.RunASync(entryPoint.Invoke); return; } @@ -102,7 +164,7 @@ public static async Task IsolateAsync(Func entryPoint, params Shim[] shims Console.WriteLine("----------------------------- Invoking ----------------------------- "); var @delegate = methodInfo.CreateDelegate(delegateType); - @delegate.DynamicInvoke(); + AsyncHelper.RunASync(() => @delegate.DynamicInvoke() as Task); } } } \ No newline at end of file diff --git a/src/Sandbox/Program.cs b/src/Sandbox/Program.cs index 983d614..2b2d2e2 100644 --- a/src/Sandbox/Program.cs +++ b/src/Sandbox/Program.cs @@ -1,68 +1,70 @@ // See https://aka.ms/new-console-template for more information using System; -using System.Reflection; -using System.Runtime.CompilerServices; using System.Threading.Tasks; -using Pose.IL; +using System.Runtime.CompilerServices; namespace Pose.Sandbox { - namespace System.Runtime.CompilerServices - { - // AsyncVoidMethodBuilder.cs in your project - public class AsyncTaskMethodBuilder - { - public void AwaitOnCompleted( - ref TAwaiter awaiter, - ref TStateMachine stateMachine - ) - where TAwaiter : INotifyCompletion - where TStateMachine : IAsyncStateMachine - { - - } - - public void AwaitUnsafeOnCompleted( - ref TAwaiter awaiter, ref TStateMachine stateMachine) - where TAwaiter : ICriticalNotifyCompletion - where TStateMachine : IAsyncStateMachine - { - - } - - public void SetStateMachine(IAsyncStateMachine stateMachine) {} - - public void SetException(Exception exception) {} - - public Task Task => null; - - public AsyncTaskMethodBuilder() - => Console.WriteLine(".ctor"); - - public static AsyncTaskMethodBuilder Create() - => new AsyncTaskMethodBuilder(); - - public void SetResult() => Console.WriteLine("SetResult"); - - public void Start(ref TStateMachine stateMachine) - where TStateMachine : IAsyncStateMachine - { - Console.WriteLine("Start"); - var methodInfos = stateMachine.GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic); - var methodRewriter = MethodRewriter.CreateRewriter(methodInfos[0], false); - var methodBase = methodRewriter.Rewrite(); - stateMachine.MoveNext(); - } - - // AwaitOnCompleted, AwaitUnsafeOnCompleted, SetException - // and SetStateMachine are empty - } - } + // namespace System.Runtime.CompilerServices + // { + // // AsyncVoidMethodBuilder.cs in your project + // public class AsyncTaskMethodBuilder + // { + // public void AwaitOnCompleted( + // ref TAwaiter awaiter, + // ref TStateMachine stateMachine + // ) + // where TAwaiter : INotifyCompletion + // where TStateMachine : IAsyncStateMachine + // { + // + // } + // + // public void AwaitUnsafeOnCompleted( + // ref TAwaiter awaiter, ref TStateMachine stateMachine) + // where TAwaiter : ICriticalNotifyCompletion + // where TStateMachine : IAsyncStateMachine + // { + // + // } + // + // public void SetStateMachine(IAsyncStateMachine stateMachine) {} + // + // public void SetException(Exception exception) {} + // + // public Task Task => null; + // + // public AsyncTaskMethodBuilder() + // => Console.WriteLine(".ctor"); + // + // public static AsyncTaskMethodBuilder Create() + // => new AsyncTaskMethodBuilder(); + // + // public void SetResult() => Console.WriteLine("SetResult"); + // + // public void Start(ref TStateMachine stateMachine) + // where TStateMachine : IAsyncStateMachine + // { + // Console.WriteLine("Start"); + // var methodInfos = stateMachine.GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic); + // var methodRewriter = MethodRewriter.CreateRewriter(methodInfos[0], false); + // var methodBase = methodRewriter.Rewrite(); + // stateMachine.MoveNext(); + // } + // + // // AwaitOnCompleted, AwaitUnsafeOnCompleted, SetException + // // and SetStateMachine are empty + // } + // } public class Program { - public static async Task GetAsyncInt() => await Task.FromResult(1); + public static async Task GetAsyncInt() + { + await Task.Delay(1000); + return await Task.FromResult(1); + } public static async Task Lol() { @@ -72,18 +74,24 @@ public static async Task Lol() public static void Main(string[] args) { - Lol().GetAwaiter().GetResult(); + //Lol().GetAwaiter().GetResult(); - // var shim = Shim - // .Replace(() => Program.GetAsyncInt()) - // .With(() => Task.FromResult(2)); - // - // PoseContext.IsolateAsync( - // async () => - // { - // var @int = await GetAsyncInt(); - // Console.WriteLine(@int); - // }, shim).GetAwaiter().GetResult(); + var shim = Shim + .Replace(() => Program.GetAsyncInt()) + .With(() => Task.FromResult(2)); + + PoseContext.Shims = new Shim[] { shim }; + + // var shim1 = Shim + // .Replace(() => System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Create()) + // .With(() => System.Runtime.CompilerServices1.AsyncTaskMethodBuilder.Create()); + + PoseContext.IsolateAsync( + async () => + { + var @int = await GetAsyncInt(); + Console.WriteLine(@int); + }, shim); /* #if NET48 Console.WriteLine("4.8");