コード例 #1
0
        public async Task RunAsync(
            ITransitionCarrier transitionCarrier,
            ITransitionData transitionData,
            CancellationToken ct)
        {
            var transitionDescriptor = await transitionData.GetTransitionDescriptorAsync(ct);

            if (transitionDescriptor.Type == TransitionType.InvokeRoutine ||
                transitionDescriptor.Type == TransitionType.ContinueRoutine)
            {
                await RunRoutineAsync(transitionCarrier, transitionData, transitionDescriptor, ct);
            }
            else
            {
                throw new InvalidOperationException();
            }
        }
コード例 #2
0
        /// <inheritdoc />
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            ITransitionData currentValue = (ITransitionData)value;

            if (currentValue == null)
            {
                return;
            }

            writer.WriteStartObject();
            {
                writer.WritePropertyName("Target");
                writer.WriteValue((IStep)null);

                writer.WritePropertyName("Conditions");
                serializer.Serialize(writer, currentValue.Conditions);
            }
            writer.WriteEndObject();
        }
コード例 #3
0
        private async Task RunRoutineAsync(
            ITransitionCarrier transitionCarrier,
            ITransitionData transitionData,
            TransitionDescriptor transitionDescriptor,
            CancellationToken ct)
        {
            using (_transitionScope.Enter(transitionDescriptor))
            {
                var transitionMonitor = _transitionScope.CurrentMonitor;

                var serviceId = await transitionData.GetServiceIdAsync(ct);

                var routineDescriptor = await transitionData.GetRoutineDescriptorAsync(ct);

                var serviceInstance =
#warning IntrinsicRoutines must be registered in the service registry, but it needs the engine IoC to resolve.
                    serviceId.ProxyName == nameof(IntrinsicRoutines)
                    ? _intrinsicRoutines
                    : _serviceProxyBuilder.Build(serviceId);
#warning check if the serviceInstance proxy is an actual non-abstract class with implementation

                // Need exact underlying type of the service implementation type to call
                // the routine method directly without using the virtual method table.
                var serviceType   = (serviceInstance as IProxy)?.ObjectType ?? serviceInstance.GetType();
                var routineMethod = _routineMethodResolver.Resolve(serviceType, routineDescriptor.MethodId);

                var serviceStateContainer = _serviceStateValueContainerProvider.CreateContainer(serviceInstance);
                var isStatefullService    = serviceStateContainer.GetCount() > 0;
                if (isStatefullService)
                {
                    await transitionData.ReadServiceStateAsync(serviceStateContainer, ct);
                }

                Task            completionTask;
                IValueContainer asmValueContainer = null;

                if (TryCreateAsyncStateMachine(routineMethod, out var asmInstance, out var asmMetadata, out completionTask))
                {
                    var isContinuation = transitionDescriptor.Type == TransitionType.ContinueRoutine;
                    asmValueContainer = await LoadRoutineStateAsync(transitionData, asmInstance, asmMetadata, isContinuation, ct);

                    asmMetadata.Owner.FieldInfo?.SetValue(asmInstance, serviceInstance);

                    transitionMonitor.OnRoutineStart(
                        serviceId,
                        routineDescriptor,
                        serviceInstance,
                        routineMethod,
                        asmInstance);

                    try
                    {
#warning possibly need to create a proxy? on a sealed ASM class? How to capture Task.Delay if it's not immediate after first MoveNext?
                        asmInstance.MoveNext();
                    }
                    catch (Exception ex)
                    {
                        // The MoveNext() must not throw, but instead complete the task with an error.
                        // try-catch is added just in case for a non-compiler-generated state machine.
                        var taskResultType = TaskAccessor.GetTaskResultType(routineMethod.ReturnType);
                        completionTask = TaskAccessor.FromException(taskResultType, ex);
                    }
                }