Пример #1
0
 private SyntaxNode CreateProxyVaraibleDeclaration(SyntaxGenerator g, GenerationNameTable nameTable, bool isAsync)
 {
     // var proxy = this.GetProxy();
     if (!isAsync)
     {
         return(g.LocalDeclarationStatement(nameTable[MemberNames.ProxyVariable],
                                            g.InvocationExpression(
                                                g.MemberAccessExpression(
                                                    g.ThisExpression(),
                                                    g.IdentifierName(nameTable[MemberNames.GetProxyMethod])
                                                    )
                                                )
                                            ));
     }
     else
     {
         // var proxy = await this.GetProxyAsync().ConfigureAwait(false);
         return
             (g.LocalDeclarationStatement(nameTable[MemberNames.ProxyVariable],
                                          g.AwaitExpression(
                                              g.InvocationExpression(
                                                  g.MemberAccessExpression(
                                                      g.InvocationExpression(
                                                          g.MemberAccessExpression(
                                                              g.ThisExpression(),
                                                              g.IdentifierName(nameTable[MemberNames.GetProxyAsyncMethod])
                                                              )
                                                          ), "ConfigureAwait"),
                                                  g.FalseLiteralExpression()
                                                  )
                                              )
                                          ));
     }
 }
Пример #2
0
        private SyntaxNode CreateStaticCloseProxyMethod(Compilation compilation, SyntaxGenerator g, GenerationNameTable nameTable, bool asAsync)
        {
            //private static void CloseProxy(System.ServiceModel.ICommunicationObject proxy, bool alwaysAbort)
            //{
            //   try
            //   {
            //      if (proxy != null && proxy.State != System.ServiceModel.CommunicationState.Closed)
            //      {
            //         if (!alwaysAbort && proxy.State != System.ServiceModel.CommunicationState.Faulted)
            //         {
            //            proxy.Close();
            //         }
            //         else
            //         {
            //            proxy.Abort();
            //         }
            //      }
            //   }
            //   catch (System.ServiceModel.CommunicationException)
            //   {
            //      proxy.Abort();
            //   }
            //   catch (System.TimeoutException)
            //   {
            //      proxy.Abort();
            //   }
            //   catch
            //   {
            //      proxy.Abort();
            //      throw;
            //   }
            //}

            return(g.MethodDeclaration(
                       asAsync ? nameTable[MemberNames.CloseProxyAsyncMethod] : nameTable[MemberNames.CloseProxyMethod],
                       accessibility: Accessibility.Private,
                       returnType: asAsync ? g.TypeExpression(compilation.RequireType <Task>()) : null,
                       modifiers: (asAsync ? DeclarationModifiers.Async : DeclarationModifiers.None) | DeclarationModifiers.Static,
                       parameters: new SyntaxNode[]
            {
                g.ParameterDeclaration("proxy", g.TypeExpression(compilation.RequireTypeByMetadataName("System.ServiceModel.ICommunicationObject"))),
                g.ParameterDeclaration("alwaysAbort", g.TypeExpression(SpecialType.System_Boolean))
            },
                       statements: new SyntaxNode[]
            {
                g.TryCatchStatement(
                    new SyntaxNode[]
                {
                    // if (proxy != null && proxy.State != System.ServiceModel.CommunicationState.Closed)
                    g.IfStatement(
                        g.LogicalAndExpression(
                            g.ReferenceNotEqualsExpression(
                                g.IdentifierName("proxy"),
                                g.NullLiteralExpression()
                                ),
                            g.ValueNotEqualsExpression(
                                g.MemberAccessExpression(
                                    g.IdentifierName("proxy"),
                                    "State"
                                    ),
                                g.DottedName("System.ServiceModel.CommunicationState.Closed")
                                )
                            ),
                        new SyntaxNode[]
                    {
                        // if (!alwaysAbort && proxy.State != System.ServiceModel.CommunicationState.Faulted)
                        g.IfStatement(
                            g.LogicalAndExpression(
                                g.LogicalNotExpression(
                                    g.IdentifierName("alwaysAbort")
                                    ),
                                g.ValueNotEqualsExpression(
                                    g.MemberAccessExpression(
                                        g.IdentifierName("proxy"),
                                        "State"
                                        ),
                                    g.DottedName("System.ServiceModel.CommunicationState.Faulted")
                                    )
                                ),
                            new SyntaxNode[]
                        {
                            g.ExpressionStatement(
                                asAsync ?
                                // await System.Threading.Tasks.Task.Factory.FromAsync(proxy.BeginClose, proxy.EndClose, null).ConfigureAwait(false);
                                AwaitExpression(g,
                                                g.InvocationExpression(
                                                    g.DottedName("System.Threading.Tasks.Task.Factory.FromAsync"),
                                                    g.DottedName("proxy.BeginClose"),
                                                    g.DottedName("proxy.EndClose"),
                                                    g.NullLiteralExpression()
                                                    )
                                                )
                                 :
                                // proxy.Close();
                                g.InvocationExpression(
                                    g.MemberAccessExpression(
                                        g.IdentifierName("proxy"),
                                        "Close"
                                        )
                                    )
                                )
                        },
                            new SyntaxNode[]
                        {
                            // proxy.Abort();
                            g.ExpressionStatement(
                                g.InvocationExpression(
                                    g.MemberAccessExpression(
                                        g.IdentifierName("proxy"),
                                        "Abort"
                                        )
                                    )
                                )
                        }
                            )
                    }
                        ),
                },
                    new SyntaxNode[]
                {
                    // catch (System.ServiceModel.CommunicationException)
                    g.CatchClause(compilation.RequireTypeByMetadataName("System.ServiceModel.CommunicationException"),
                                  new SyntaxNode[]
                    {
                        // proxy.Abort();
                        g.ExpressionStatement(
                            g.InvocationExpression(
                                g.MemberAccessExpression(
                                    g.IdentifierName("proxy"),
                                    "Abort"
                                    )
                                )
                            )
                    }
                                  ),
                    g.CatchClause(compilation.RequireTypeByMetadataName("System.TimeoutException"),
                                  new SyntaxNode[]
                    {
                        // proxy.Abort();
                        g.ExpressionStatement(
                            g.InvocationExpression(
                                g.MemberAccessExpression(
                                    g.IdentifierName("proxy"),
                                    "Abort"
                                    )
                                )
                            )
                    }
                                  ),
                    g.CatchClause(
                        new SyntaxNode[]
                    {
                        // proxy.Abort();
                        g.ExpressionStatement(
                            g.InvocationExpression(
                                g.MemberAccessExpression(
                                    g.IdentifierName("proxy"),
                                    "Abort"
                                    )
                                )
                            ),
                        g.ThrowStatement()
                    }
                        )
                }
                    )
            }
                       ));
        }
Пример #3
0
        public Task <ClassDeclarationSyntax> GenerateClientClass(SemanticModel semanticModel, SyntaxGenerator gen, INamedTypeSymbol proxyInterface, string name, Accessibility accessibility, bool includeCancellableAsyncMethods, bool suppressWarningComments, MemberAccessibility constructorAccessibility, bool withInternalProxy)
        {
            if (name == null)
            {
                if (proxyInterface.Name.StartsWith("I"))
                {
                    name = proxyInterface.Name.Substring(1);
                }

                if (name.EndsWith("Proxy"))
                {
                    name = name.Substring(0, name.Length - "Proxy".Length);
                }

                if (!name.EndsWith("Client"))
                {
                    name = name + "Client";
                }
            }


            SyntaxNode targetClass = gen.ClassDeclaration(name,
                                                          baseType: gen.TypeExpression(semanticModel.Compilation.RequireType <MarshalByRefObject>()),
                                                          accessibility: accessibility,
                                                          modifiers: DeclarationModifiers.Sealed);

            targetClass = gen.AddWarningCommentIf(!suppressWarningComments, targetClass);

            targetClass = gen.AddInterfaceType(targetClass, gen.TypeExpression(semanticModel.Compilation.GetSpecialType(SpecialType.System_IDisposable)));
            targetClass = gen.AddInterfaceType(targetClass, gen.TypeExpression(proxyInterface));

            IEnumerable <IMethodSymbol> methods = GetOperationContractMethods(semanticModel.Compilation, proxyInterface).ToArray();

            GenerationNameTable nameTable = new GenerationNameTable(methods.Select(m => m.Name).Concat(new[] { name }));


            #region Private Fields

            // ==> private IProxy m_cachedProxy;
            SyntaxNode cachedProxyField =
                gen.FieldDeclaration(nameTable[MemberNames.CachedProxyField], gen.TypeExpression(proxyInterface), Accessibility.Private, DeclarationModifiers.None)
                .PrependLeadingTrivia(gen.CreateRegionTrivia("Private Fields"));

            targetClass = gen.AddMembers(targetClass, cachedProxyField);

            // ==> private readonly Func<IProxy> m_proxyFactory;
            SyntaxNode proxyFactoryTypeExpression = gen.TypeExpression(semanticModel.Compilation.RequireTypeByMetadataName("System.Func`1").Construct(proxyInterface));

            targetClass = gen.AddMembers(targetClass, gen.FieldDeclaration(nameTable[MemberNames.ProxyFactoryField], proxyFactoryTypeExpression, Accessibility.Private, DeclarationModifiers.ReadOnly)
                                         .AddTrailingTrivia(gen.CreateEndRegionTrivia()).AddNewLineTrivia());

            #endregion


            #region Constructors

            // Constructor
            SyntaxNode constructor = gen.ConstructorDeclaration(
                parameters: new[] { gen.ParameterDeclaration("proxyFactory", proxyFactoryTypeExpression) },
                accessibility: withInternalProxy?Accessibility.Private: ToAccessibility(constructorAccessibility)
                );

            constructor = gen.AddWarningCommentIf(!suppressWarningComments, constructor);
            constructor = constructor.PrependLeadingTrivia(gen.CreateRegionTrivia("Constructors"));

            constructor = gen.WithStatements(constructor,
                                             new[]
            {
                // ==> if (proxyFactory == null)
                // ==>   throw new System.ArgumentNullException("proxyFactory");
                gen.ThrowIfNullStatement("proxyFactory"),

                // ==> m_proxyFactory = proxyFactory
                gen.AssignmentStatement(
                    gen.MemberAccessExpression(
                        gen.ThisExpression(),
                        gen.IdentifierName(nameTable[MemberNames.ProxyFactoryField])),
                    gen.IdentifierName("proxyFactory")
                    )
            }
                                             ).AddNewLineTrivia();

            if (!withInternalProxy)
            {
                constructor = constructor.AddTrailingTrivia(gen.CreateEndRegionTrivia()).AddNewLineTrivia();
            }

            targetClass = gen.AddMembers(targetClass, constructor);

            ClassDeclarationSyntax proxyClass = null;
            if (withInternalProxy)
            {
                IEnumerable <IMethodSymbol> ctors;
                proxyClass = GenerateProxyClass(semanticModel, gen, proxyInterface, nameTable[MemberNames.ProxyClass], Accessibility.Private, suppressWarningComments, MemberAccessibility.Public, out ctors)
                             .PrependLeadingTrivia(gen.CreateRegionTrivia("Proxy Class").Insert(0, gen.NewLine()))
                             .AddTrailingTrivia(gen.CreateEndRegionTrivia());

                // Generate one constructor for each of the proxy's constructors.
                foreach (var ctorEntry in ctors.AsSmartEnumerable())
                {
                    var ctor       = ctorEntry.Value;
                    var targetCtor = gen.ConstructorDeclaration(ctor);

                    var lambda = gen.ValueReturningLambdaExpression(
                        gen.ObjectCreationExpression(gen.IdentifierName(gen.GetName(proxyClass)), ctor.Parameters.Select(p => gen.IdentifierName(p.Name)))
                        );

                    targetCtor = gen.WithThisConstructorInitializer(targetCtor, new[] { lambda });

                    targetCtor = gen.AddWarningCommentIf(!suppressWarningComments, targetCtor);
                    targetCtor = gen.WithAccessibility(targetCtor, ToAccessibility(constructorAccessibility));

                    if (ctorEntry.IsLast)
                    {
                        targetCtor = targetCtor.AddTrailingTrivia(gen.CreateEndRegionTrivia()).AddNewLineTrivia();
                    }

                    targetClass = gen.AddMembers(targetClass, targetCtor.AddNewLineTrivia());
                }
            }

            #endregion

            #region Operation Contract Methods

            // ==> catch
            // ==> {
            // ==>    this.CloseProxy(false);
            // ==>    throw;
            // ==> }
            var catchAndCloseProxyStatement = gen.CatchClause(new SyntaxNode[]
            {
                // ==> this.CloseProxy(false);
                gen.ExpressionStatement(
                    gen.InvocationExpression(
                        gen.MemberAccessExpression(
                            gen.ThisExpression(),
                            nameTable[MemberNames.CloseProxyMethod]
                            ),
                        gen.FalseLiteralExpression()
                        )
                    ),

                // throw;
                gen.ThrowStatement()
            });


            foreach (var sourceMethodEntry in methods.AsSmartEnumerable())
            {
                var sourceMethod = sourceMethodEntry.Value;

                using (nameTable.PushScope(sourceMethod.Parameters.Select(p => p.Name)))
                {
                    bool isAsync = ReturnsTask(semanticModel.Compilation, sourceMethod);
                    bool isVoid  = sourceMethod.ReturnType.SpecialType == SpecialType.System_Void || sourceMethod.ReturnType.Equals(semanticModel.Compilation.RequireType <Task>());

                    SyntaxNode targetMethod = gen.MethodDeclaration(sourceMethod);

                    if (sourceMethodEntry.IsFirst)
                    {
                        targetMethod = targetMethod.PrependLeadingTrivia(gen.CreateRegionTrivia("Contract Methods")).AddLeadingTrivia(gen.NewLine());
                    }

                    targetMethod = gen.AddWarningCommentIf(!suppressWarningComments, targetMethod);

                    targetMethod = gen.WithModifiers(targetMethod, isAsync ? DeclarationModifiers.Async : DeclarationModifiers.None);


                    targetMethod = gen.WithStatements(targetMethod, new SyntaxNode[]
                    {
                        // ==> try {
                        gen.TryCatchStatement(new SyntaxNode[]
                        {
                            CreateProxyVaraibleDeclaration(gen, nameTable, isAsync),
                            CreateProxyInvocationStatement(semanticModel.Compilation, gen, nameTable, sourceMethod)
                        }, new SyntaxNode[]
                        {
                            catchAndCloseProxyStatement
                        }
                                              )
                    });

                    targetMethod = targetMethod.AddNewLineTrivia();

                    if (sourceMethodEntry.IsLast && !(isAsync && includeCancellableAsyncMethods))
                    {
                        targetMethod = targetMethod.AddTrailingTrivia(gen.CreateEndRegionTrivia()).AddNewLineTrivia();
                    }

                    targetClass = gen.AddMembers(targetClass, targetMethod);

                    if (isAsync && includeCancellableAsyncMethods)
                    {
                        targetMethod = gen.MethodDeclaration(sourceMethod);
                        targetMethod = gen.AddParameters(targetMethod, new[] { gen.ParameterDeclaration(nameTable[MemberNames.CancellationTokenParameter], gen.TypeExpression(semanticModel.Compilation.RequireType <CancellationToken>())) });
                        targetMethod = gen.WithModifiers(targetMethod, isAsync ? DeclarationModifiers.Async : DeclarationModifiers.None);


                        targetMethod = gen.WithStatements(targetMethod, new SyntaxNode[]
                        {
                            // ==> try {
                            gen.TryCatchStatement(new SyntaxNode[]
                            {
                                CreateProxyVaraibleDeclaration(gen, nameTable, isAsync),
                                CreateCancellableProxyInvocationStatement(semanticModel.Compilation, gen, nameTable, sourceMethod)
                            }, new SyntaxNode[]
                            {
                                catchAndCloseProxyStatement
                            }
                                                  )
                        });


                        targetMethod = gen.AddWarningCommentIf(!suppressWarningComments, targetMethod.AddNewLineTrivia());

                        if (sourceMethodEntry.IsLast)
                        {
                            targetMethod = targetMethod.AddTrailingTrivia(gen.CreateEndRegionTrivia()).AddNewLineTrivia();
                        }

                        targetClass = gen.AddMembers(targetClass, targetMethod);
                    }
                }
            }

            #endregion

            #region Internal Methods

            targetClass = gen.AddMembers(targetClass, gen.AddWarningCommentIf(!suppressWarningComments, CreateGetProxyMethod(semanticModel.Compilation, gen, proxyInterface, nameTable, false).AddLeadingTrivia(gen.CreateRegionTrivia("Private Methods")).AddNewLineTrivia()));
            targetClass = gen.AddMembers(targetClass, gen.AddWarningCommentIf(!suppressWarningComments, CreateGetProxyMethod(semanticModel.Compilation, gen, proxyInterface, nameTable, true).AddNewLineTrivia()));
            targetClass = gen.AddMembers(targetClass, gen.AddWarningCommentIf(!suppressWarningComments, CreateStaticCloseProxyMethod(semanticModel.Compilation, gen, nameTable, false).AddNewLineTrivia()));
            targetClass = gen.AddMembers(targetClass, gen.AddWarningCommentIf(!suppressWarningComments, CreateStaticCloseProxyMethod(semanticModel.Compilation, gen, nameTable, true).AddNewLineTrivia()));
            targetClass = gen.AddMembers(targetClass, gen.AddWarningCommentIf(!suppressWarningComments, CreateCloseProxyMethod(semanticModel.Compilation, gen, nameTable, false).AddNewLineTrivia()));
            targetClass = gen.AddMembers(targetClass, gen.AddWarningCommentIf(!suppressWarningComments, CreateCloseProxyMethod(semanticModel.Compilation, gen, nameTable, true).AddNewLineTrivia()));
            targetClass = gen.AddMembers(targetClass, gen.AddWarningCommentIf(!suppressWarningComments, CreateEnsureProxyMethod(semanticModel.Compilation, gen, nameTable, false).AddNewLineTrivia()));
            targetClass = gen.AddMembers(targetClass, gen.AddWarningCommentIf(!suppressWarningComments, CreateEnsureProxyMethod(semanticModel.Compilation, gen, nameTable, true).AddTrailingTrivia(gen.CreateEndRegionTrivia()).AddNewLineTrivia()));
            targetClass = gen.AddMembers(targetClass, CreateDisposeMethods(semanticModel.Compilation, gen, nameTable, suppressWarningComments));

            if (withInternalProxy)
            {
                targetClass = gen.AddMembers(targetClass, proxyClass);
            }

            #endregion


            targetClass = AddGeneratedCodeAttribute(gen, targetClass);
            return(Task.FromResult((ClassDeclarationSyntax)targetClass));
        }
Пример #4
0
 private SyntaxNode CreateGetProxyMethod(Compilation compilation, SyntaxGenerator g, INamedTypeSymbol proxyInterface, GenerationNameTable nameTable, bool isAsync)
 {
     //private IProxy GetProxy()
     //{
     //   EnsureProxy();
     //   return m_cachedProxy;
     //}
     return(g.MethodDeclaration(
                isAsync ? nameTable[MemberNames.GetProxyAsyncMethod] : nameTable[MemberNames.GetProxyMethod],
                returnType: g.TypeExpression(isAsync ? compilation.RequireType(typeof(Task <>)).Construct(proxyInterface) : proxyInterface),
                accessibility: Accessibility.Private,
                modifiers: isAsync ? DeclarationModifiers.Async : DeclarationModifiers.None,
                statements: new SyntaxNode[]
     {
         g.ExpressionStatement(
             AwaitExpressionIfAsync(g, isAsync,
                                    g.InvocationExpression(
                                        g.MemberAccessExpression(
                                            g.ThisExpression(),
                                            isAsync ? nameTable[MemberNames.EnsureProxyAsyncMethod] : nameTable[MemberNames.EnsureProxyMethod]
                                            )
                                        )
                                    )
             ),
         g.ReturnStatement(
             g.MemberAccessExpression(
                 g.ThisExpression(),
                 nameTable[MemberNames.CachedProxyField]
                 )
             )
     }
                ));
 }
Пример #5
0
        private SyntaxNode CreateCancellableProxyInvocationStatement(Compilation compilation, SyntaxGenerator g, GenerationNameTable nameTable, IMethodSymbol sourceMethod)
        {
            //using (cancellationToken.Register(s => CloseProxy((System.ServiceModel.ICommunicationObject)s, true), proxy, false))
            string stateVariableName = GetUniqueParameterName("s", sourceMethod);

            return(g.UsingStatement(
                       g.InvocationExpression(
                           g.MemberAccessExpression(
                               g.IdentifierName(nameTable[MemberNames.CancellationTokenParameter]),
                               "Register"
                               ),
                           g.ValueReturningLambdaExpression(
                               stateVariableName,
                               g.InvocationExpression(
                                   g.IdentifierName(nameTable[MemberNames.CloseProxyMethod]),
                                   g.CastExpression(
                                       compilation.RequireTypeByMetadataName("System.ServiceModel.ICommunicationObject"),
                                       g.IdentifierName(stateVariableName)
                                       ),
                                   g.TrueLiteralExpression()
                                   )
                               ),
                           g.IdentifierName(nameTable[MemberNames.ProxyVariable]),
                           g.FalseLiteralExpression()
                           ),
                       new SyntaxNode[]
            {
                CreateProxyInvocationStatement(compilation, g, nameTable, sourceMethod)
            }
                       ));
        }
Пример #6
0
        private IEnumerable <SyntaxNode> CreateDisposeMethods(Compilation compilation, SyntaxGenerator g, GenerationNameTable nameTable, bool suppressWarningComments)
        {
            yield return(g.AddWarningCommentIf(!suppressWarningComments,
                                               g.MethodDeclaration(
                                                   "Dispose",
                                                   accessibility: Accessibility.Public,
                                                   statements: new SyntaxNode[]
            {
                g.InvocationExpression(
                    g.MemberAccessExpression(
                        g.ThisExpression(),
                        "Dispose"
                        ),
                    g.TrueLiteralExpression()
                    ),
                g.InvocationExpression(
                    g.MemberAccessExpression(
                        g.TypeExpression(compilation.RequireTypeByMetadataName("System.GC")),
                        "SuppressFinalize"
                        ),
                    g.ThisExpression()
                    )
            }
                                                   ))
                         .PrependLeadingTrivia(g.CreateRegionTrivia("IDisposable")));


            yield return(g.AddWarningCommentIf(!suppressWarningComments, g.MethodDeclaration(
                                                   "Dispose",
                                                   parameters: new SyntaxNode[] { g.ParameterDeclaration("disposing", g.TypeExpression(SpecialType.System_Boolean)) },
                                                   accessibility: Accessibility.Private,
                                                   statements: new SyntaxNode[]
            {
                g.IfStatement(
                    g.ValueEqualsExpression(
                        g.IdentifierName("disposing"),
                        g.TrueLiteralExpression()
                        ),
                    new SyntaxNode[]
                {
                    g.TryCatchStatement(
                        new SyntaxNode[]
                    {
                        g.ExpressionStatement(
                            g.InvocationExpression(
                                g.MemberAccessExpression(
                                    g.ThisExpression(),
                                    nameTable[MemberNames.CloseProxyMethod]
                                    ),
                                g.FalseLiteralExpression()
                                )
                            )
                    },
                        new SyntaxNode[]
                    {
                        g.CatchClause(new SyntaxNode [0])
                    }
                        )
                }
                    )
            }
                                                   )).AddTrailingTrivia(g.CreateEndRegionTrivia()));
        }
 private SyntaxNode CreateProxyVaraibleDeclaration(SyntaxGenerator g, GenerationNameTable nameTable, bool isAsync)
 {
    // var proxy = this.GetProxy();
    if (!isAsync)
    {
       return g.LocalDeclarationStatement(nameTable[MemberNames.ProxyVariable],
                                        g.InvocationExpression(
                                           g.MemberAccessExpression(
                                              g.ThisExpression(),
                                              g.IdentifierName(nameTable[MemberNames.GetProxyMethod])
                                           )
                                        )
                                     );
    }
    else
    {
       // var proxy = await this.GetProxyAsync().ConfigureAwait(false);                                                
       return
          g.LocalDeclarationStatement(nameTable[MemberNames.ProxyVariable],
             g.AwaitExpression(
                g.InvocationExpression(
                   g.MemberAccessExpression(
                      g.InvocationExpression(
                         g.MemberAccessExpression(
                            g.ThisExpression(),
                            g.IdentifierName(nameTable[MemberNames.GetProxyAsyncMethod])
                         )
                      ), "ConfigureAwait"),
                   g.FalseLiteralExpression()
                )
             )
          );
    }
 }
      private SyntaxNode CreateEnsureProxyMethod(Compilation compilation, SyntaxGenerator g, GenerationNameTable nameTable, bool asAsync)
      {
         /*
            private async System.Threading.Tasks.Task EnsureProxyAsync()
            {
               if (m_cachedProxy != null && (
                   ((System.ServiceModel.ICommunicationObject)m_cachedProxy).State == System.ServiceModel.CommunicationState.Faulted ||
                   ((System.ServiceModel.ICommunicationObject)m_cachedProxy).State == System.ServiceModel.CommunicationState.Closed))
               {
                  await CloseProxyAsync().ConfigureAwait(false);
               }

               if (m_cachedProxy == null)
               {
                  var proxy = m_proxyFactory();
                  await System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)proxy).BeginOpen, ((System.ServiceModel.ICommunicationObject)proxy).EndOpen, null).ConfigureAwait(false);
                  m_cachedProxy = proxy;
               }
            }
         */
         return
            g.MethodDeclaration(
               asAsync ? nameTable[MemberNames.EnsureProxyAsyncMethod] : nameTable[MemberNames.EnsureProxyMethod],
               returnType: asAsync ? g.TypeExpression(compilation.RequireType<Task>()) : null,
               accessibility: Accessibility.Private,
               modifiers: asAsync ? DeclarationModifiers.Async : DeclarationModifiers.None,
               statements: new SyntaxNode[]
               {
                  //if (m_cachedProxy != null && (
                  //             ((System.ServiceModel.ICommunicationObject)m_cachedProxy).State == System.ServiceModel.CommunicationState.Faulted ||
                  //             ((System.ServiceModel.ICommunicationObject)m_cachedProxy).State == System.ServiceModel.CommunicationState.Closed))
                  g.IfStatement(
                     g.LogicalAndExpression(
                        // m_cachedProxy != null
                        g.ReferenceNotEqualsExpression(
                           g.MemberAccessExpression(
                              g.ThisExpression(),
                              nameTable[MemberNames.CachedProxyField]
                           ),
                           g.NullLiteralExpression()
                        ),
                        g.LogicalOrExpression(
                           // ((System.ServiceModel.ICommunicationObject)m_cachedProxy).State == System.ServiceModel.CommunicationState.Faulted
                           g.ValueEqualsExpression(
                              g.MemberAccessExpression(
                                 g.CastExpression(
                                    compilation.RequireTypeByMetadataName("System.ServiceModel.ICommunicationObject"),
                                    g.MemberAccessExpression(
                                       g.ThisExpression(),
                                       nameTable[MemberNames.CachedProxyField]
                                    )
                                 ),
                                 "State"
                              ),
                              g.DottedName("System.ServiceModel.CommunicationState.Faulted")
                           ),
                           // ((System.ServiceModel.ICommunicationObject)m_cachedProxy).State == System.ServiceModel.CommunicationState.Faulted
                           g.ValueEqualsExpression(
                              g.MemberAccessExpression(
                                 g.CastExpression(
                                    compilation.RequireTypeByMetadataName("System.ServiceModel.ICommunicationObject"),
                                    g.MemberAccessExpression(
                                       g.ThisExpression(),
                                       nameTable[MemberNames.CachedProxyField]
                                    )
                                 ),
                                 "State"
                              ),
                              g.DottedName("System.ServiceModel.CommunicationState.Closed")
                           )
                        )
                     ),
                     new SyntaxNode[]
                     {
                        // await CloseProxyAsync(false).ConfigureAwait(false);
                        // or
                        // CloseProxy(false);
                        AwaitExpressionIfAsync(g, asAsync,
                           g.InvocationExpression(
                              g.MemberAccessExpression(
                                 g.ThisExpression(),
                                 asAsync ? nameTable[MemberNames.CloseProxyAsyncMethod] : nameTable[MemberNames.CloseProxyMethod]
                              ),
                              g.FalseLiteralExpression()
                           )
                        )
                     }
                  ),
                  g.IfStatement(
                     g.ReferenceEqualsExpression(
                        g.MemberAccessExpression(
                           g.ThisExpression(),
                           nameTable[MemberNames.CachedProxyField]
                        ),
                        g.NullLiteralExpression()
                     ),
                     new SyntaxNode[]
                     {
                        g.LocalDeclarationStatement(
                           "proxy",
                           g.InvocationExpression(
                              g.MemberAccessExpression(
                                 g.ThisExpression(),
                                 nameTable[MemberNames.ProxyFactoryField]
                              )
                           )
                        ),
                        g.ExpressionStatement(
                           asAsync ?
                           AwaitExpression(g,
                                    g.InvocationExpression(
                                       g.DottedName("System.Threading.Tasks.Task.Factory.FromAsync"),
                                       g.MemberAccessExpression(
                                          g.CastExpression(
                                              compilation.RequireTypeByMetadataName("System.ServiceModel.ICommunicationObject"),
                                              g.IdentifierName("proxy")
                                          ),
                                          "BeginOpen"
                                       ),
                                       g.MemberAccessExpression(
                                          g.CastExpression(
                                              compilation.RequireTypeByMetadataName("System.ServiceModel.ICommunicationObject"),
                                              g.IdentifierName("proxy")
                                          ),
                                          "EndOpen"
                                       ),
                                       g.NullLiteralExpression()
                                    )
                                 )
                           :
                           g.InvocationExpression(
                              g.MemberAccessExpression(
                                 g.CastExpression(
                                    compilation.RequireTypeByMetadataName("System.ServiceModel.ICommunicationObject"),
                                    g.IdentifierName("proxy")
                                 ),
                                 "Open"
                              )
                           )
                        ),
                        g.AssignmentStatement(
                           g.MemberAccessExpression(
                              g.ThisExpression(),
                              nameTable[MemberNames.CachedProxyField]
                           ),
                           g.IdentifierName("proxy")
                        )
                     }
                  )
               }
            );

      }
      private IEnumerable<SyntaxNode> CreateDisposeMethods(Compilation compilation, SyntaxGenerator g, GenerationNameTable nameTable, bool suppressWarningComments)
      {
         yield return g.AddWarningCommentIf(!suppressWarningComments,
         g.MethodDeclaration(
            "Dispose",
            accessibility: Accessibility.Public,
            statements: new SyntaxNode[]
            {
               g.InvocationExpression(
                  g.MemberAccessExpression(
                     g.ThisExpression(),
                     "Dispose"
                  ),
                  g.TrueLiteralExpression()
               ),
               g.InvocationExpression(
                  g.MemberAccessExpression(
                     g.TypeExpression(compilation.RequireTypeByMetadataName("System.GC")),
                     "SuppressFinalize"
                  ),
                  g.ThisExpression()
               )
            }
         ))
         .PrependLeadingTrivia(g.CreateRegionTrivia("IDisposable"));


         yield return g.AddWarningCommentIf(!suppressWarningComments, g.MethodDeclaration(
            "Dispose",
            parameters: new SyntaxNode[] { g.ParameterDeclaration("disposing", g.TypeExpression(SpecialType.System_Boolean)) },
            accessibility: Accessibility.Private,
            statements: new SyntaxNode[]
            {
               g.IfStatement(
                  g.ValueEqualsExpression(
                     g.IdentifierName("disposing"),
                     g.TrueLiteralExpression()
                  ),
                  new SyntaxNode[]
                  {
                     g.TryCatchStatement(
                        new SyntaxNode[]
                        {
                           g.ExpressionStatement(
                              g.InvocationExpression(
                                 g.MemberAccessExpression(
                                    g.ThisExpression(),
                                    nameTable[MemberNames.CloseProxyMethod]
                                 ),
                                 g.FalseLiteralExpression()
                              )
                           )
                        },
                        new SyntaxNode[]
                        {
                           g.CatchClause(new SyntaxNode [0])
                        }
                     )
                  }
               )
            }
         )).AddTrailingTrivia(g.CreateEndRegionTrivia());
      }
      private SyntaxNode CreateStaticCloseProxyMethod(Compilation compilation, SyntaxGenerator g, GenerationNameTable nameTable, bool asAsync)
      {
         //private static void CloseProxy(System.ServiceModel.ICommunicationObject proxy, bool alwaysAbort)
         //{
         //   try
         //   {
         //      if (proxy != null && proxy.State != System.ServiceModel.CommunicationState.Closed)
         //      {
         //         if (!alwaysAbort && proxy.State != System.ServiceModel.CommunicationState.Faulted)
         //         {
         //            proxy.Close();
         //         }
         //         else
         //         {
         //            proxy.Abort();
         //         }
         //      }
         //   }
         //   catch (System.ServiceModel.CommunicationException)
         //   {
         //      proxy.Abort();
         //   }
         //   catch (System.TimeoutException)
         //   {
         //      proxy.Abort();
         //   }
         //   catch
         //   {
         //      proxy.Abort();
         //      throw;
         //   }
         //}                  
         
         return g.MethodDeclaration(
            asAsync ? nameTable[MemberNames.CloseProxyAsyncMethod] : nameTable[MemberNames.CloseProxyMethod],
            accessibility: Accessibility.Private,
            returnType: asAsync ? g.TypeExpression(compilation.RequireType<Task>()) : null,
            modifiers: (asAsync ? DeclarationModifiers.Async : DeclarationModifiers.None) | DeclarationModifiers.Static,
            parameters: new SyntaxNode[]
            {
               g.ParameterDeclaration("proxy", g.TypeExpression(compilation.RequireTypeByMetadataName("System.ServiceModel.ICommunicationObject"))),
               g.ParameterDeclaration("alwaysAbort", g.TypeExpression(SpecialType.System_Boolean))

            },
            statements: new SyntaxNode[]
            {
               g.TryCatchStatement(
                  new SyntaxNode[]
                  {
                     // if (proxy != null && proxy.State != System.ServiceModel.CommunicationState.Closed)
                     g.IfStatement(
                        g.LogicalAndExpression(
                           g.ReferenceNotEqualsExpression(
                              g.IdentifierName("proxy"),
                              g.NullLiteralExpression()
                           ),
                           g.ValueNotEqualsExpression(
                              g.MemberAccessExpression(
                                 g.IdentifierName("proxy"),
                                 "State"
                              ),
                              g.DottedName("System.ServiceModel.CommunicationState.Closed")
                           )
                        ),
                        new SyntaxNode[]
                        {
                           // if (!alwaysAbort && proxy.State != System.ServiceModel.CommunicationState.Faulted)
                           g.IfStatement(
                              g.LogicalAndExpression(
                                 g.LogicalNotExpression(
                                    g.IdentifierName("alwaysAbort")
                                 ),
                                 g.ValueNotEqualsExpression(
                                    g.MemberAccessExpression(
                                       g.IdentifierName("proxy"),
                                       "State"
                                    ),
                                    g.DottedName("System.ServiceModel.CommunicationState.Faulted")
                                 )
                              ),
                              new SyntaxNode[]
                              {
                                 g.ExpressionStatement(
                                 asAsync ? 
                                 // await System.Threading.Tasks.Task.Factory.FromAsync(proxy.BeginClose, proxy.EndClose, null).ConfigureAwait(false);
                                 AwaitExpression(g,
                                    g.InvocationExpression(
                                       g.DottedName("System.Threading.Tasks.Task.Factory.FromAsync"),
                                       g.DottedName("proxy.BeginClose"),
                                       g.DottedName("proxy.EndClose"),
                                       g.NullLiteralExpression()
                                    )
                                 )
                                 :
                                 // proxy.Close();
                                 g.InvocationExpression(
                                       g.MemberAccessExpression(
                                          g.IdentifierName("proxy"),
                                          "Close"
                                       )
                                    )
                                 )
                              },
                              new SyntaxNode[]
                              {
                                 // proxy.Abort();
                                 g.ExpressionStatement(
                                    g.InvocationExpression(
                                       g.MemberAccessExpression(
                                          g.IdentifierName("proxy"),
                                          "Abort"
                                       )
                                    )
                                 )
                              }
                           )
                        }
                     ),
                  },
                  new SyntaxNode[]
                  {
                     // catch (System.ServiceModel.CommunicationException)
                     g.CatchClause(compilation.RequireTypeByMetadataName("System.ServiceModel.CommunicationException"),
                        new SyntaxNode[]
                        {
                           // proxy.Abort();
                           g.ExpressionStatement(
                              g.InvocationExpression(
                                 g.MemberAccessExpression(
                                    g.IdentifierName("proxy"),
                                    "Abort"
                                 )
                              )
                           )
                        }
                     ),
                     g.CatchClause(compilation.RequireTypeByMetadataName("System.TimeoutException"),
                        new SyntaxNode[]
                        {
                           // proxy.Abort();
                           g.ExpressionStatement(
                              g.InvocationExpression(
                                 g.MemberAccessExpression(
                                    g.IdentifierName("proxy"),
                                    "Abort"
                                 )
                              )
                           )
                        }
                     ),
                     g.CatchClause(
                        new SyntaxNode[]
                        {
                           // proxy.Abort();
                           g.ExpressionStatement(
                              g.InvocationExpression(
                                 g.MemberAccessExpression(
                                    g.IdentifierName("proxy"),
                                    "Abort"
                                 )
                              )
                           ),
                           g.ThrowStatement()
                        }
                     )

                  }
               )
            }
         );
      }
 private SyntaxNode CreateCloseProxyMethod(Compilation compilation, SyntaxGenerator g, GenerationNameTable nameTable, bool asAsync)
 {
    return
       g.MethodDeclaration(
          asAsync ? nameTable[MemberNames.CloseProxyAsyncMethod] : nameTable[MemberNames.CloseProxyMethod],
          returnType: asAsync ? g.TypeExpression(compilation.RequireType<Task>()) : null,
          parameters: new SyntaxNode[] { g.ParameterDeclaration("alwaysAbort", g.TypeExpression(SpecialType.System_Boolean)) },
          modifiers: asAsync ? DeclarationModifiers.Async : DeclarationModifiers.None,
          accessibility: Accessibility.Private,
          statements: new SyntaxNode[]
          {
             g.IfStatement(
                g.ReferenceNotEqualsExpression(
                   g.IdentifierName(nameTable[MemberNames.CachedProxyField]),
                   g.NullLiteralExpression()
                ),
                new SyntaxNode[]
                {
                   g.LocalDeclarationStatement(
                      "proxy",
                      g.TryCastExpression(
                         g.MemberAccessExpression(
                            g.ThisExpression(),
                            nameTable[MemberNames.CachedProxyField]
                         ),
                         compilation.RequireTypeByMetadataName("System.ServiceModel.ICommunicationObject")
                      )
                   ),
                   g.TryFinallyStatement(
                      new SyntaxNode[]
                      {
                         AwaitExpressionIfAsync(g, asAsync,
                            g.InvocationExpression(
                               g.IdentifierName(asAsync ? nameTable[MemberNames.CloseProxyAsyncMethod] : nameTable[MemberNames.CloseProxyMethod]),
                               g.IdentifierName("proxy"),
                               g.IdentifierName("alwaysAbort")
                            )
                         )
                      },
                      new SyntaxNode[]
                      {
                         g.AssignmentStatement(
                            g.MemberAccessExpression(
                               g.ThisExpression(),
                               nameTable[MemberNames.CachedProxyField]
                            ),
                            g.NullLiteralExpression()
                         )
                      }
                   )
                }
             )
          }
       );
 }
      public Task<ClassDeclarationSyntax> GenerateClientClass(SemanticModel semanticModel, SyntaxGenerator gen, INamedTypeSymbol proxyInterface, string name, Accessibility accessibility, bool includeCancellableAsyncMethods, bool suppressWarningComments, MemberAccessibility constructorAccessibility, bool withInternalProxy)
      {
         if (name == null)
         {
            if (proxyInterface.Name.StartsWith("I"))
               name = proxyInterface.Name.Substring(1);

            if (name.EndsWith("Proxy"))
               name = name.Substring(0, name.Length - "Proxy".Length);

            if (!name.EndsWith("Client"))
               name = name + "Client";
         }

         
         SyntaxNode targetClass = gen.ClassDeclaration(name, 
            baseType: gen.TypeExpression(semanticModel.Compilation.RequireType<MarshalByRefObject>()), 
            accessibility: accessibility, 
            modifiers: DeclarationModifiers.Sealed);

         targetClass = gen.AddWarningCommentIf(!suppressWarningComments, targetClass);

         targetClass = gen.AddInterfaceType(targetClass, gen.TypeExpression(semanticModel.Compilation.GetSpecialType(SpecialType.System_IDisposable)));
         targetClass = gen.AddInterfaceType(targetClass, gen.TypeExpression(proxyInterface));

         IEnumerable<IMethodSymbol> methods = GetOperationContractMethods(semanticModel.Compilation, proxyInterface).ToArray();

         GenerationNameTable nameTable = new GenerationNameTable(methods.Select(m => m.Name).Concat(new[] { name }));


         #region Private Fields

         // ==> private IProxy m_cachedProxy;
         SyntaxNode cachedProxyField =
            gen.FieldDeclaration(nameTable[MemberNames.CachedProxyField], gen.TypeExpression(proxyInterface), Accessibility.Private, DeclarationModifiers.None)
            .PrependLeadingTrivia(gen.CreateRegionTrivia("Private Fields"));

         targetClass = gen.AddMembers(targetClass, cachedProxyField);

         // ==> private readonly Func<IProxy> m_proxyFactory;
         SyntaxNode proxyFactoryTypeExpression = gen.TypeExpression(semanticModel.Compilation.RequireTypeByMetadataName("System.Func`1").Construct(proxyInterface));

         targetClass = gen.AddMembers(targetClass, gen.FieldDeclaration(nameTable[MemberNames.ProxyFactoryField], proxyFactoryTypeExpression, Accessibility.Private, DeclarationModifiers.ReadOnly)
            .AddTrailingTrivia(gen.CreateEndRegionTrivia()).AddNewLineTrivia());

         #endregion


         #region Constructors

         // Constructor         
         SyntaxNode constructor = gen.ConstructorDeclaration(
            parameters: new[] { gen.ParameterDeclaration("proxyFactory", proxyFactoryTypeExpression) },
            accessibility: withInternalProxy ? Accessibility.Private : ToAccessibility(constructorAccessibility)
         );

         constructor = gen.AddWarningCommentIf(!suppressWarningComments, constructor);
         constructor = constructor.PrependLeadingTrivia(gen.CreateRegionTrivia("Constructors"));

         constructor = gen.WithStatements(constructor,
            new[]
            {
               // ==> if (proxyFactory == null)
               // ==>   throw new System.ArgumentNullException("proxyFactory");
               gen.ThrowIfNullStatement("proxyFactory"),
               
               // ==> m_proxyFactory = proxyFactory
               gen.AssignmentStatement(
                  gen.MemberAccessExpression(
                     gen.ThisExpression(),
                     gen.IdentifierName(nameTable[MemberNames.ProxyFactoryField])),
                  gen.IdentifierName("proxyFactory")
               )
            }
         ).AddNewLineTrivia();

         if (!withInternalProxy)
            constructor = constructor.AddTrailingTrivia(gen.CreateEndRegionTrivia()).AddNewLineTrivia();

         targetClass = gen.AddMembers(targetClass, constructor);

         ClassDeclarationSyntax proxyClass = null;
         if (withInternalProxy)
         {
            IEnumerable<IMethodSymbol> ctors;
            proxyClass = GenerateProxyClass(semanticModel, gen, proxyInterface, nameTable[MemberNames.ProxyClass], Accessibility.Private, suppressWarningComments, MemberAccessibility.Public, out ctors)
                                                   .PrependLeadingTrivia(gen.CreateRegionTrivia("Proxy Class").Insert(0, gen.NewLine()))
                                                   .AddTrailingTrivia(gen.CreateEndRegionTrivia());

            // Generate one constructor for each of the proxy's constructors.
            foreach (var ctorEntry in ctors.AsSmartEnumerable())
            {
               var ctor = ctorEntry.Value;
               var targetCtor = gen.ConstructorDeclaration(ctor);

               var lambda = gen.ValueReturningLambdaExpression(                  
                  gen.ObjectCreationExpression(gen.IdentifierName(gen.GetName(proxyClass)), ctor.Parameters.Select(p => gen.IdentifierName(p.Name)))
               );

               targetCtor = gen.WithThisConstructorInitializer(targetCtor, new[] { lambda });

               targetCtor = gen.AddWarningCommentIf(!suppressWarningComments, targetCtor);
               targetCtor = gen.WithAccessibility(targetCtor, ToAccessibility(constructorAccessibility));
               
               if (ctorEntry.IsLast)
               {
                  targetCtor = targetCtor.AddTrailingTrivia(gen.CreateEndRegionTrivia()).AddNewLineTrivia();
               }

               targetClass = gen.AddMembers(targetClass, targetCtor.AddNewLineTrivia());
            }


         }

         #endregion

         #region Operation Contract Methods

         // ==> catch
         // ==> {
         // ==>    this.CloseProxy(false);
         // ==>    throw;
         // ==> }
         var catchAndCloseProxyStatement = gen.CatchClause(new SyntaxNode[]
            {
               // ==> this.CloseProxy(false);
               gen.ExpressionStatement(
                  gen.InvocationExpression(
                     gen.MemberAccessExpression(
                        gen.ThisExpression(),
                        nameTable[MemberNames.CloseProxyMethod]
                     ),
                     gen.FalseLiteralExpression()
                  )
               ),

               // throw;
               gen.ThrowStatement()
            });


         foreach (var sourceMethodEntry in methods.AsSmartEnumerable())
         {
            var sourceMethod = sourceMethodEntry.Value;

            using (nameTable.PushScope(sourceMethod.Parameters.Select(p => p.Name)))
            {
               bool isAsync = ReturnsTask(semanticModel.Compilation, sourceMethod);
               bool isVoid = sourceMethod.ReturnType.SpecialType == SpecialType.System_Void || sourceMethod.ReturnType.Equals(semanticModel.Compilation.RequireType<Task>());

               SyntaxNode targetMethod = gen.MethodDeclaration(sourceMethod);

               if (sourceMethodEntry.IsFirst)
                  targetMethod = targetMethod.PrependLeadingTrivia(gen.CreateRegionTrivia("Contract Methods")).AddLeadingTrivia(gen.NewLine());

               targetMethod = gen.AddWarningCommentIf(!suppressWarningComments, targetMethod);

               targetMethod = gen.WithModifiers(targetMethod, isAsync ? DeclarationModifiers.Async : DeclarationModifiers.None);


               targetMethod = gen.WithStatements(targetMethod, new SyntaxNode[]
                  {
                  // ==> try {
                  gen.TryCatchStatement(new SyntaxNode[]
                     {
                        CreateProxyVaraibleDeclaration(gen, nameTable, isAsync),
                        CreateProxyInvocationStatement(semanticModel.Compilation, gen, nameTable, sourceMethod)

                     }, new SyntaxNode[]
                     {
                        catchAndCloseProxyStatement
                     }
                  )
                  });

               targetMethod = targetMethod.AddNewLineTrivia();

               if (sourceMethodEntry.IsLast && !(isAsync && includeCancellableAsyncMethods))
                  targetMethod = targetMethod.AddTrailingTrivia(gen.CreateEndRegionTrivia()).AddNewLineTrivia();

               targetClass = gen.AddMembers(targetClass, targetMethod);

               if (isAsync && includeCancellableAsyncMethods)
               {
                  targetMethod = gen.MethodDeclaration(sourceMethod);
                  targetMethod = gen.AddParameters(targetMethod, new[] { gen.ParameterDeclaration(nameTable[MemberNames.CancellationTokenParameter], gen.TypeExpression(semanticModel.Compilation.RequireType<CancellationToken>())) });
                  targetMethod = gen.WithModifiers(targetMethod, isAsync ? DeclarationModifiers.Async : DeclarationModifiers.None);


                  targetMethod = gen.WithStatements(targetMethod, new SyntaxNode[]
                     {
                     // ==> try {
                     gen.TryCatchStatement(new SyntaxNode[]
                        {
                           CreateProxyVaraibleDeclaration(gen, nameTable, isAsync),
                           CreateCancellableProxyInvocationStatement(semanticModel.Compilation, gen, nameTable, sourceMethod)

                        }, new SyntaxNode[]
                        {
                           catchAndCloseProxyStatement
                        }
                     )
                     });


                  targetMethod = gen.AddWarningCommentIf(!suppressWarningComments, targetMethod.AddNewLineTrivia());

                  if (sourceMethodEntry.IsLast)
                     targetMethod = targetMethod.AddTrailingTrivia(gen.CreateEndRegionTrivia()).AddNewLineTrivia();

                  targetClass = gen.AddMembers(targetClass, targetMethod);
               }
            }
         }

         #endregion

         #region Internal Methods

         targetClass = gen.AddMembers(targetClass, gen.AddWarningCommentIf(!suppressWarningComments, CreateGetProxyMethod(semanticModel.Compilation, gen, proxyInterface, nameTable, false).AddLeadingTrivia(gen.CreateRegionTrivia("Private Methods")).AddNewLineTrivia()));
         targetClass = gen.AddMembers(targetClass, gen.AddWarningCommentIf(!suppressWarningComments, CreateGetProxyMethod(semanticModel.Compilation, gen, proxyInterface, nameTable, true).AddNewLineTrivia()));
         targetClass = gen.AddMembers(targetClass, gen.AddWarningCommentIf(!suppressWarningComments, CreateStaticCloseProxyMethod(semanticModel.Compilation, gen, nameTable, false).AddNewLineTrivia()));
         targetClass = gen.AddMembers(targetClass, gen.AddWarningCommentIf(!suppressWarningComments, CreateStaticCloseProxyMethod(semanticModel.Compilation, gen, nameTable, true).AddNewLineTrivia()));
         targetClass = gen.AddMembers(targetClass, gen.AddWarningCommentIf(!suppressWarningComments, CreateCloseProxyMethod(semanticModel.Compilation, gen, nameTable, false).AddNewLineTrivia()));
         targetClass = gen.AddMembers(targetClass, gen.AddWarningCommentIf(!suppressWarningComments, CreateCloseProxyMethod(semanticModel.Compilation, gen, nameTable, true).AddNewLineTrivia()));
         targetClass = gen.AddMembers(targetClass, gen.AddWarningCommentIf(!suppressWarningComments, CreateEnsureProxyMethod(semanticModel.Compilation, gen, nameTable, false).AddNewLineTrivia()));
         targetClass = gen.AddMembers(targetClass, gen.AddWarningCommentIf(!suppressWarningComments, CreateEnsureProxyMethod(semanticModel.Compilation, gen, nameTable, true).AddTrailingTrivia(gen.CreateEndRegionTrivia()).AddNewLineTrivia()));
         targetClass = gen.AddMembers(targetClass, CreateDisposeMethods(semanticModel.Compilation, gen, nameTable, suppressWarningComments));

         if (withInternalProxy)
         {
            targetClass = gen.AddMembers(targetClass, proxyClass);
         }

         #endregion


         targetClass = AddGeneratedCodeAttribute(gen, targetClass);
         return Task.FromResult((ClassDeclarationSyntax)targetClass);
      }
 private SyntaxNode CreateGetProxyMethod(Compilation compilation, SyntaxGenerator g, INamedTypeSymbol proxyInterface, GenerationNameTable nameTable, bool isAsync)
 {
    //private IProxy GetProxy()
    //{
    //   EnsureProxy();
    //   return m_cachedProxy;
    //}
    return g.MethodDeclaration(
       isAsync ? nameTable[MemberNames.GetProxyAsyncMethod] : nameTable[MemberNames.GetProxyMethod],
       returnType: g.TypeExpression(isAsync ? compilation.RequireType(typeof(Task<>)).Construct(proxyInterface) : proxyInterface),
       accessibility: Accessibility.Private,
       modifiers: isAsync ? DeclarationModifiers.Async : DeclarationModifiers.None,
       statements: new SyntaxNode[]
       {
          g.ExpressionStatement(
             AwaitExpressionIfAsync(g, isAsync,
                g.InvocationExpression(
                   g.MemberAccessExpression(
                      g.ThisExpression(),
                      isAsync ? nameTable[MemberNames.EnsureProxyAsyncMethod] : nameTable[MemberNames.EnsureProxyMethod]
                   )
                )
             )
          ),
          g.ReturnStatement(
             g.MemberAccessExpression(
                g.ThisExpression(),
                nameTable[MemberNames.CachedProxyField]
             )
          )
       }
    );
 }
 private SyntaxNode CreateCancellableProxyInvocationStatement(Compilation compilation, SyntaxGenerator g, GenerationNameTable nameTable, IMethodSymbol sourceMethod)
 {
    //using (cancellationToken.Register(s => CloseProxy((System.ServiceModel.ICommunicationObject)s, true), proxy, false))
    string stateVariableName = GetUniqueParameterName("s", sourceMethod);
    return g.UsingStatement(
       g.InvocationExpression(
          g.MemberAccessExpression(
             g.IdentifierName(nameTable[MemberNames.CancellationTokenParameter]),
                "Register"
          ),
          g.ValueReturningLambdaExpression(
             stateVariableName,
             g.InvocationExpression(
                g.IdentifierName(nameTable[MemberNames.CloseProxyMethod]),
                g.CastExpression(
                   compilation.RequireTypeByMetadataName("System.ServiceModel.ICommunicationObject"),
                   g.IdentifierName(stateVariableName)
                ),
                g.TrueLiteralExpression()
             )
          ),
          g.IdentifierName(nameTable[MemberNames.ProxyVariable]),
          g.FalseLiteralExpression()
       ),
       new SyntaxNode[]
       {
          CreateProxyInvocationStatement(compilation, g, nameTable, sourceMethod)
       }
    );
 }
Пример #15
0
 private SyntaxNode CreateCloseProxyMethod(Compilation compilation, SyntaxGenerator g, GenerationNameTable nameTable, bool asAsync)
 {
     return
         (g.MethodDeclaration(
              asAsync ? nameTable[MemberNames.CloseProxyAsyncMethod] : nameTable[MemberNames.CloseProxyMethod],
              returnType: asAsync ? g.TypeExpression(compilation.RequireType <Task>()) : null,
              parameters: new SyntaxNode[] { g.ParameterDeclaration("alwaysAbort", g.TypeExpression(SpecialType.System_Boolean)) },
              modifiers: asAsync?DeclarationModifiers.Async: DeclarationModifiers.None,
              accessibility: Accessibility.Private,
              statements: new SyntaxNode[]
     {
         g.IfStatement(
             g.ReferenceNotEqualsExpression(
                 g.IdentifierName(nameTable[MemberNames.CachedProxyField]),
                 g.NullLiteralExpression()
                 ),
             new SyntaxNode[]
         {
             g.LocalDeclarationStatement(
                 "proxy",
                 g.TryCastExpression(
                     g.MemberAccessExpression(
                         g.ThisExpression(),
                         nameTable[MemberNames.CachedProxyField]
                         ),
                     compilation.RequireTypeByMetadataName("System.ServiceModel.ICommunicationObject")
                     )
                 ),
             g.TryFinallyStatement(
                 new SyntaxNode[]
             {
                 AwaitExpressionIfAsync(g, asAsync,
                                        g.InvocationExpression(
                                            g.IdentifierName(asAsync ? nameTable[MemberNames.CloseProxyAsyncMethod] : nameTable[MemberNames.CloseProxyMethod]),
                                            g.IdentifierName("proxy"),
                                            g.IdentifierName("alwaysAbort")
                                            )
                                        )
             },
                 new SyntaxNode[]
             {
                 g.AssignmentStatement(
                     g.MemberAccessExpression(
                         g.ThisExpression(),
                         nameTable[MemberNames.CachedProxyField]
                         ),
                     g.NullLiteralExpression()
                     )
             }
                 )
         }
             )
     }
              ));
 }
 public ScopeDisposer(GenerationNameTable table)
 {
    m_table = table;
 }
Пример #17
0
 private SyntaxNode CreateEnsureProxyMethod(Compilation compilation, SyntaxGenerator g, GenerationNameTable nameTable, bool asAsync)
 {
     /*
      * private async System.Threading.Tasks.Task EnsureProxyAsync()
      * {
      *    if (m_cachedProxy != null && (
      *        ((System.ServiceModel.ICommunicationObject)m_cachedProxy).State == System.ServiceModel.CommunicationState.Faulted ||
      *        ((System.ServiceModel.ICommunicationObject)m_cachedProxy).State == System.ServiceModel.CommunicationState.Closed))
      *    {
      *       await CloseProxyAsync().ConfigureAwait(false);
      *    }
      *
      *    if (m_cachedProxy == null)
      *    {
      *       var proxy = m_proxyFactory();
      *       await System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)proxy).BeginOpen, ((System.ServiceModel.ICommunicationObject)proxy).EndOpen, null).ConfigureAwait(false);
      *       m_cachedProxy = proxy;
      *    }
      * }
      */
     return
         (g.MethodDeclaration(
              asAsync ? nameTable[MemberNames.EnsureProxyAsyncMethod] : nameTable[MemberNames.EnsureProxyMethod],
              returnType: asAsync ? g.TypeExpression(compilation.RequireType <Task>()) : null,
              accessibility: Accessibility.Private,
              modifiers: asAsync ? DeclarationModifiers.Async : DeclarationModifiers.None,
              statements: new SyntaxNode[]
     {
         //if (m_cachedProxy != null && (
         //             ((System.ServiceModel.ICommunicationObject)m_cachedProxy).State == System.ServiceModel.CommunicationState.Faulted ||
         //             ((System.ServiceModel.ICommunicationObject)m_cachedProxy).State == System.ServiceModel.CommunicationState.Closed))
         g.IfStatement(
             g.LogicalAndExpression(
                 // m_cachedProxy != null
                 g.ReferenceNotEqualsExpression(
                     g.MemberAccessExpression(
                         g.ThisExpression(),
                         nameTable[MemberNames.CachedProxyField]
                         ),
                     g.NullLiteralExpression()
                     ),
                 g.LogicalOrExpression(
                     // ((System.ServiceModel.ICommunicationObject)m_cachedProxy).State == System.ServiceModel.CommunicationState.Faulted
                     g.ValueEqualsExpression(
                         g.MemberAccessExpression(
                             g.CastExpression(
                                 compilation.RequireTypeByMetadataName("System.ServiceModel.ICommunicationObject"),
                                 g.MemberAccessExpression(
                                     g.ThisExpression(),
                                     nameTable[MemberNames.CachedProxyField]
                                     )
                                 ),
                             "State"
                             ),
                         g.DottedName("System.ServiceModel.CommunicationState.Faulted")
                         ),
                     // ((System.ServiceModel.ICommunicationObject)m_cachedProxy).State == System.ServiceModel.CommunicationState.Faulted
                     g.ValueEqualsExpression(
                         g.MemberAccessExpression(
                             g.CastExpression(
                                 compilation.RequireTypeByMetadataName("System.ServiceModel.ICommunicationObject"),
                                 g.MemberAccessExpression(
                                     g.ThisExpression(),
                                     nameTable[MemberNames.CachedProxyField]
                                     )
                                 ),
                             "State"
                             ),
                         g.DottedName("System.ServiceModel.CommunicationState.Closed")
                         )
                     )
                 ),
             new SyntaxNode[]
         {
             // await CloseProxyAsync(false).ConfigureAwait(false);
             // or
             // CloseProxy(false);
             AwaitExpressionIfAsync(g, asAsync,
                                    g.InvocationExpression(
                                        g.MemberAccessExpression(
                                            g.ThisExpression(),
                                            asAsync ? nameTable[MemberNames.CloseProxyAsyncMethod] : nameTable[MemberNames.CloseProxyMethod]
                                            ),
                                        g.FalseLiteralExpression()
                                        )
                                    )
         }
             ),
         g.IfStatement(
             g.ReferenceEqualsExpression(
                 g.MemberAccessExpression(
                     g.ThisExpression(),
                     nameTable[MemberNames.CachedProxyField]
                     ),
                 g.NullLiteralExpression()
                 ),
             new SyntaxNode[]
         {
             g.LocalDeclarationStatement(
                 "proxy",
                 g.InvocationExpression(
                     g.MemberAccessExpression(
                         g.ThisExpression(),
                         nameTable[MemberNames.ProxyFactoryField]
                         )
                     )
                 ),
             g.ExpressionStatement(
                 asAsync ?
                 AwaitExpression(g,
                                 g.InvocationExpression(
                                     g.DottedName("System.Threading.Tasks.Task.Factory.FromAsync"),
                                     g.MemberAccessExpression(
                                         g.CastExpression(
                                             compilation.RequireTypeByMetadataName("System.ServiceModel.ICommunicationObject"),
                                             g.IdentifierName("proxy")
                                             ),
                                         "BeginOpen"
                                         ),
                                     g.MemberAccessExpression(
                                         g.CastExpression(
                                             compilation.RequireTypeByMetadataName("System.ServiceModel.ICommunicationObject"),
                                             g.IdentifierName("proxy")
                                             ),
                                         "EndOpen"
                                         ),
                                     g.NullLiteralExpression()
                                     )
                                 )
                    :
                 g.InvocationExpression(
                     g.MemberAccessExpression(
                         g.CastExpression(
                             compilation.RequireTypeByMetadataName("System.ServiceModel.ICommunicationObject"),
                             g.IdentifierName("proxy")
                             ),
                         "Open"
                         )
                     )
                 ),
             g.AssignmentStatement(
                 g.MemberAccessExpression(
                     g.ThisExpression(),
                     nameTable[MemberNames.CachedProxyField]
                     ),
                 g.IdentifierName("proxy")
                 )
         }
             )
     }
              ));
 }
Пример #18
0
        private SyntaxNode CreateProxyInvocationStatement(Compilation compilation, SyntaxGenerator g, GenerationNameTable nameTable, IMethodSymbol sourceMethod)
        {
            bool isAsync = ReturnsTask(compilation, sourceMethod);
            bool isVoid  = IsVoid(compilation, sourceMethod);

            // proxy.Method(arg1, arg2, ...);
            SyntaxNode invocation = g.InvocationExpression(
                g.MemberAccessExpression(
                    g.IdentifierName(nameTable[MemberNames.ProxyVariable]),
                    sourceMethod.Name
                    ),
                sourceMethod.Parameters.Select(p => g.IdentifierName(p.Name))
                );

            if (isAsync)
            {
                // await proxy.Method(arg1, arg2, ...).ConfigureAwait(false);
                invocation =
                    g.AwaitExpression(
                        g.InvocationExpression(
                            g.MemberAccessExpression(
                                invocation,
                                "ConfigureAwait"
                                ),
                            g.FalseLiteralExpression()
                            )
                        );
            }

            if (isVoid)
            {
                invocation = g.ExpressionStatement(invocation);
            }
            else
            {
                invocation = g.ReturnStatement(invocation);
            }

            return(invocation);
        }
 public ScopeDisposer(GenerationNameTable table)
 {
     m_table = table;
 }
      private SyntaxNode CreateProxyInvocationStatement(Compilation compilation, SyntaxGenerator g, GenerationNameTable nameTable, IMethodSymbol sourceMethod)
      {
         bool isAsync = ReturnsTask(compilation, sourceMethod);
         bool isVoid = IsVoid(compilation, sourceMethod);

         // proxy.Method(arg1, arg2, ...);
         SyntaxNode invocation = g.InvocationExpression(
                                    g.MemberAccessExpression(
                                       g.IdentifierName(nameTable[MemberNames.ProxyVariable]),
                                       sourceMethod.Name
                                    ),
                                    sourceMethod.Parameters.Select(p => g.IdentifierName(p.Name))
                                 );

         if (isAsync)
         {
            // await proxy.Method(arg1, arg2, ...).ConfigureAwait(false);
            invocation =
               g.AwaitExpression(
                  g.InvocationExpression(
                     g.MemberAccessExpression(
                        invocation,
                        "ConfigureAwait"
                     ),
                     g.FalseLiteralExpression()
                  )
               );
         }

         if (isVoid)
         {
            invocation = g.ExpressionStatement(invocation);
         }
         else
         {
            invocation = g.ReturnStatement(invocation);
         }

         return invocation;

      }