コード例 #1
0
        protected override void SetupStateMachine()
        {
            _stateMachineClass.AddBaseType(TypeSystemServices.ValueTypeType);
            _stateMachineClass.AddBaseType(TypeSystemServices.IAsyncStateMachineType);
            _stateMachineClass.Modifiers |= TypeMemberModifiers.Final;
            var ctr = TypeSystemServices.Map(typeof(AsyncStateMachineAttribute)).GetConstructors().Single();

            _method.Method.Attributes.Add(
                CodeBuilder.CreateAttribute(
                    ctr,
                    CodeBuilder.CreateTypeofExpression(_stateMachineClass.Entity)));
            AsyncMethodBuilderMemberCollection.TryCreate(
                TypeSystemServices,
                _method.Method,
                MethodGenArg(true),
                out _asyncMethodBuilderMemberCollection);

            _state = (IField)_stateMachineClass.AddInternalField(UniqueName("State"), TypeSystemServices.IntType).Entity;
            _asyncMethodBuilderField = _stateMachineClass.AddInternalField(
                UniqueName("Builder"),
                _asyncMethodBuilderMemberCollection.BuilderType);
            CreateSetStateMachine();
            PreprocessMethod();
        }
コード例 #2
0
        private void FixAsyncMethodBody(MethodInvocationExpression stateMachineConstructorInvocation)
        {
            var method = _method.Method;
            // If the async method's result type is a type parameter of the method, then the AsyncTaskMethodBuilder<T>
            // needs to use the method's type parameters inside the rewritten method body. All other methods generated
            // during async rewriting are members of the synthesized state machine struct, and use the type parameters
            // structs type parameters.
            AsyncMethodBuilderMemberCollection methodScopeAsyncMethodBuilderMemberCollection;

            if (!AsyncMethodBuilderMemberCollection.TryCreate(
                    TypeSystemServices,
                    method,
                    MethodGenArg(false),
                    out methodScopeAsyncMethodBuilderMemberCollection))
            {
                throw new NotImplementedException("Custom async patterns are not supported");
            }

            var bodyBuilder     = new Block();
            var builderVariable = CodeBuilder.DeclareTempLocal(method, methodScopeAsyncMethodBuilderMemberCollection.BuilderType);

            var stateMachineType = stateMachineConstructorInvocation.ExpressionType;

            var stateMachineVariable = CodeBuilder.DeclareLocal(
                method,
                UniqueName("async"),
                stateMachineType);

            bodyBuilder.Add(CodeBuilder.CreateAssignment(
                                CodeBuilder.CreateLocalReference(stateMachineVariable),
                                stateMachineConstructorInvocation));

            // local.$builder = System.Runtime.CompilerServices.AsyncTaskMethodBuilder<typeArgs>.Create();
            bodyBuilder.Add(
                CodeBuilder.CreateAssignment(
                    CodeBuilder.CreateMemberReference(
                        CodeBuilder.CreateLocalReference(stateMachineVariable),
                        ExternalFieldEntity((IField)_asyncMethodBuilderField.Entity, stateMachineType)),
                    CodeBuilder.CreateMethodInvocation(methodScopeAsyncMethodBuilderMemberCollection.CreateBuilder)));

            // local.$stateField = NotStartedStateMachine
            bodyBuilder.Add(
                CodeBuilder.CreateAssignment(
                    CodeBuilder.CreateMemberReference(
                        CodeBuilder.CreateLocalReference(stateMachineVariable),
                        ExternalFieldEntity(_state, stateMachineType)),
                    CodeBuilder.CreateIntegerLiteral(StateMachineStates.NotStartedStateMachine)));

            bodyBuilder.Add(
                CodeBuilder.CreateAssignment(
                    CodeBuilder.CreateLocalReference(builderVariable),
                    CodeBuilder.CreateMemberReference(
                        CodeBuilder.CreateLocalReference(stateMachineVariable),
                        ExternalFieldEntity((IField)_asyncMethodBuilderField.Entity, stateMachineType))));

            // local.$builder.Start(ref local) -- binding to the method AsyncTaskMethodBuilder<typeArgs>.Start()
            bodyBuilder.Add(
                CodeBuilder.CreateMethodInvocation(
                    CodeBuilder.CreateLocalReference(builderVariable),
                    methodScopeAsyncMethodBuilderMemberCollection.Start.GenericInfo.ConstructMethod(stateMachineType),
                    CodeBuilder.CreateLocalReference(stateMachineVariable)));

            var methodBuilderField = stateMachineType.ConstructedInfo == null
                        ? (IField)_asyncMethodBuilderField.Entity
                        : stateMachineType.ConstructedInfo.Map((IField)_asyncMethodBuilderField.Entity);

            bodyBuilder.Add(method.ReturnType.Entity == TypeSystemServices.VoidType
                ? new ReturnStatement()
                : new ReturnStatement(
                                CodeBuilder.CreateMethodInvocation(
                                    CodeBuilder.CreateMemberReference(
                                        CodeBuilder.CreateLocalReference(stateMachineVariable),
                                        methodBuilderField),
                                    methodScopeAsyncMethodBuilderMemberCollection.Task.GetGetMethod())));

            _method.Method.Body = bodyBuilder;
        }