private static Func <IAsyncStateMachine, Task> CompileGetCompletionTaskFunc(AsyncStateMachineMetadata metadata) { var stateMachineArg = Expression.Variable(typeof(IAsyncStateMachine), "sm"); var stateMachine = Expression.Convert(stateMachineArg, metadata.StateMachineType); var accessBuilder = Expression.MakeMemberAccess(stateMachine, metadata.Builder.FieldInfo); var taskProperty = metadata.Builder.FieldInfo.FieldType.GetProperty(nameof(AsyncTaskMethodBuilder.Task)); var getTask = Expression.MakeMemberAccess(accessBuilder, taskProperty); var lambda = Expression.Lambda(getTask, stateMachineArg); return((Func <IAsyncStateMachine, Task>)lambda.Compile()); }
public IAsyncStateMachineAccessor Create(AsyncStateMachineMetadata metadata) { lock (_accessorMap) { if (!_accessorMap.TryGetValue(metadata, out var accessor)) { accessor = new AsyncStateMachineAccessor(metadata); _accessorMap.Add(metadata, accessor); } return(accessor); } }
private static Func <IAsyncStateMachine> CompileCreateInstanceFunc(AsyncStateMachineMetadata metadata) { var stateMachine = Expression.Variable(metadata.StateMachineType, "sm"); var newInstance = Expression.New(metadata.StateMachineType); var newStateMachine = Expression.Assign(stateMachine, newInstance); var newBuilder = Expression.Call(null, metadata.Builder.FieldInfo.FieldType.GetMethod(nameof(AsyncTaskMethodBuilder.Create))); var setBuilder = Expression.Assign(Expression.MakeMemberAccess(stateMachine, metadata.Builder.FieldInfo), newBuilder); var setState = Expression.Assign(Expression.MakeMemberAccess(stateMachine, metadata.State.FieldInfo), Expression.Constant(-1)); var funcBody = Expression.Block(new[] { stateMachine }, newStateMachine, setBuilder, setState, Expression.Convert(stateMachine, typeof(IAsyncStateMachine))); var lambda = Expression.Lambda(funcBody); return((Func <IAsyncStateMachine>)lambda.Compile()); }
public AsyncStateMachineAccessor(AsyncStateMachineMetadata metadata) { _createInstanceFunc = CompileCreateInstanceFunc(metadata); _getCompletionTaskFunc = CompileGetCompletionTaskFunc(metadata); }