예제 #1
0
        public MemberAccessibility ExtractMemberAccessibility()
        {
            MemberAccessibility accessibility = default(MemberAccessibility);

            if (MethodInfo.Attributes.HasFlag(MethodAttributes.PrivateScope))
            {
                accessibility = accessibility | MemberAccessibility.PrivateScope;
            }
            if (MethodInfo.Attributes.HasFlag(MethodAttributes.Private))
            {
                accessibility = accessibility | MemberAccessibility.Private;
            }
            if (MethodInfo.Attributes.HasFlag(MethodAttributes.FamANDAssem))
            {
                accessibility = accessibility | MemberAccessibility.FamilyAndAssembly;
            }
            if (MethodInfo.Attributes.HasFlag(MethodAttributes.Assembly))
            {
                accessibility = accessibility | MemberAccessibility.Assembly;
            }
            if (MethodInfo.Attributes.HasFlag(MethodAttributes.Family))
            {
                accessibility = accessibility | MemberAccessibility.Family;
            }
            if (MethodInfo.Attributes.HasFlag(MethodAttributes.FamORAssem))
            {
                accessibility = accessibility | MemberAccessibility.FamilyOrAssembly;
            }
            if (MethodInfo.Attributes.HasFlag(MethodAttributes.Public))
            {
                accessibility = accessibility | MemberAccessibility.Public;
            }

            return(accessibility);
        }
 internal TypedMemberDataBase(MemberReference member, MemberAccessibility accessibility, TypeReference type, bool isTypeDynamic, MemberFlags flags, DeclaringTypeData declaringType)
     : base(member, accessibility, flags, declaringType)
 {
     this.Type          = TypeData.FromType(type);
     this.IsTypeDynamic = isTypeDynamic;
     Debug.Assert(this.Type != null, "Unable to get the TypeData.");
 }
 internal MemberDataBase(MemberReference underlyingMember, MemberAccessibility accessibility, MemberFlags memberFlags, DeclaringTypeData declaringType)
 {
     this.Accessibility = accessibility;
     this.DeclaringType = declaringType;
     this.MemberFlags   = memberFlags;
     this.Name          = underlyingMember.Name;
 }
예제 #4
0
 internal TypeDefinitionData(string name, MemberAccessibility accessibility, MemberFlags memberFlags, TypeKind typeKind, AssemblyData assembly, string fullName, TypeDefinitionFlags typeDefinitionFlags, bool delegateReturnTypeIsDynamic)
     : base(name, accessibility, memberFlags, typeKind)
 {
     _assembly = assembly;
     this.DelegateReturnTypeIsDynamic = delegateReturnTypeIsDynamic;
     this.FullName            = fullName;
     this.TypeDefinitionFlags = typeDefinitionFlags;
 }
 internal GenericTypeParameterData(string name, MemberAccessibility accessibility, MemberFlags memberFlags, TypeKind typeKind, AssemblyData assembly, System.Reflection.GenericParameterAttributes genericParameterAttributes, int genericParameterPosition)
     : base(name, accessibility, memberFlags, typeKind)
 {
     _assembly        = assembly;
     this.Constraints = new List <TypeData>();
     this.GenericParameterAttributes = genericParameterAttributes;
     this.GenericParameterPosition   = genericParameterPosition;
 }
예제 #6
0
        internal TypeDefinitionData(TypeDefinition type, MemberAccessibility accessibility, DeclaringTypeData declaringType, AssemblyData assembly)
            : base(type, accessibility, declaringType)
        {
            _assembly = assembly;

            var typeFlags = TypeDefinitionFlags.None;

            if (this.TypeKind == TypeKind.Class && type.CustomAttributes.Any(a => a.AttributeType.EqualsType(typeof(ExtensionAttribute))))
            {
                typeFlags |= TypeDefinitionFlags.ExtensionsClass;
            }

            if (this.IsSealed == false)
            {
                // A type can only be inherited if it has at least one externally visible constructor and any abstract members are also externally visible.
                var canBeIherited = type.Methods.Where(c => c.IsConstructor && c.GetAccessibility() != null).Any();
                if (this.CanBeInherited)
                {
                    if (type.Methods.Where(m => m.IsSpecialName == false && m.IsConstructor == false && m.GetAccessibility() == null && m.IsAbstract).Any() ||
                        type.Events.Where(e => e.AddMethod.GetAccessibility() == null && e.AddMethod.IsAbstract).Any() ||
                        type.Properties.Where(p => p.GetMethod != null ? p.GetMethod.GetAccessibility() == null && p.GetMethod.IsAbstract : p.SetMethod.GetAccessibility() == null && p.SetMethod.IsAbstract).Any())
                    {
                        canBeIherited = false;
                    }
                }

                if (canBeIherited)
                {
                    typeFlags |= TypeDefinitionFlags.CanBeInherited;
                }
            }

            if (this.TypeKind == TypeKind.Enum)
            {
                var flagsAttributeData = type.CustomAttributes.Where(a => a.AttributeType.EqualsType(typeof(FlagsAttribute))).SingleOrDefault();
                if (flagsAttributeData != null)
                {
                    typeFlags |= TypeDefinitionFlags.FlagsEnum;
                }
            }

            this.TypeDefinitionFlags = typeFlags;
            this.FullName            = type.FullName;

            var renamedAttributeData = type.CustomAttributes.Where(a => a.AttributeType.EqualsType(typeof(TypeRenamedAttribute))).SingleOrDefault();

            if (renamedAttributeData != null)
            {
                this.OldName = renamedAttributeData.ConstructorArguments[0].Value as string;
            }

            var typeForwardedFromAttribute = type.CustomAttributes.Where(a => a.AttributeType.EqualsType(typeof(TypeForwardedFromAttribute))).SingleOrDefault();

            if (typeForwardedFromAttribute != null)
            {
                this.AssemblyData.AddForwardedTypeFromTarget(this, typeForwardedFromAttribute.ConstructorArguments[0].Value.ToString());
            }
        }
예제 #7
0
 /// <summary>
 /// Creates an instance of the <see cref="MemberDescriptor"/> class.
 /// </summary>
 /// <param name="memberAccessibility">
 /// Defines the accessibility of the member (Public, NonPublic, or Any)
 /// </param>
 /// <param name="memberScope">
 /// Defines the declaration scope of the member (Static, Instance, or Any)
 /// </param>
 /// <param name="caseInsensitive">
 /// Specifies whether the member identifier should be matched without case sensitivity.
 /// The default value for this parameter is <c>false</c>
 /// </param>
 private MemberDescriptor(
     MemberAccessibility memberAccessibility,
     MemberScope memberScope = MemberScope.Instance,
     bool caseInsensitive    = false)
 {
     MemberAccessibility = memberAccessibility;
     MemberScope         = memberScope;
     CaseInsensitive     = caseInsensitive;
 }
예제 #8
0
        /// <summary>
        /// Extension method to return all properties and fields from an object.
        /// </summary>
        /// <param name="t">Specifies the type of object to examine.</param>
        /// <param name="accessiblity">Specifies which properties and fields to return.</param>
        /// <returns></returns>
        public static IEnumerable <MemberInfo> GetPropertiesAndFields(this Type t, MemberAccessibility accessiblity = MemberAccessibility.All)
        {
            BindingFlags searchFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy;

            IEnumerable <MemberInfo>   fields     = t.GetFields(searchFlags);
            IEnumerable <PropertyInfo> properties = t.GetProperties(searchFlags);

            switch (accessiblity)
            {
            case MemberAccessibility.Readable:
                properties = properties.Where(p => p.CanRead);
                break;

            case MemberAccessibility.Writeable:
                properties = properties.Where(p => p.CanWrite);
                break;
            }
            return(properties.Concat(fields));
        }
예제 #9
0
        private static bool IsMemberReflectable(IMember member, MemberAccessibility memberReflectability)
        {
            switch (memberReflectability)
            {
            case MemberAccessibility.None:
                return(false);

            case MemberAccessibility.PublicAndProtected:
                return(!member.IsPrivate && !member.IsInternal);

            case MemberAccessibility.NonPrivate:
                return(!member.IsPrivate);

            case MemberAccessibility.All:
                return(true);

            default:
                throw new ArgumentException("reflectability");
            }
        }
예제 #10
0
        private MethodData(MethodDefinition methodDefinition, MemberAccessibility accessibility, DeclaringTypeData declaringType)
            : base(methodDefinition, accessibility, declaringType)
        {
            if (methodDefinition.HasGenericParameters)
            {
                MemberDataBase declaringMember = null;
                if (methodDefinition.DeclaringType.IsGenericInstance == false)
                {
                    declaringMember = this;
                }

                this.GenericParameters = Utilities.GetGenericParameters(methodDefinition.GenericParameters, declaringMember);
            }
            else
            {
                this.GenericParameters = GenericTypeParameterData.EmptyList;
            }

            this.IsExtensionMethod =
                declaringType.IsExtensionsClass &&
                methodDefinition.CustomAttributes.Any(a => a.AttributeType.EqualsType(typeof(ExtensionAttribute)));
        }
        private static Accessibility ToAccessibility(MemberAccessibility accessibility)
        {
            switch (accessibility)
            {
            case MemberAccessibility.Public:
                return(Accessibility.Public);

            case MemberAccessibility.Protected:
                return(Accessibility.Protected);

            case MemberAccessibility.Internal:
                return(Accessibility.Internal);

            case MemberAccessibility.Private:
                return(Accessibility.Private);

            case MemberAccessibility.ProtectedInternal:
                return(Accessibility.ProtectedOrInternal);

            default:
                throw new NotSupportedException($"Invalid accessibility {accessibility}.");
            }
        }
        public DefaultPropertyDefinition(TypeDefinition typeDef,
            string name,
            GetMethod getter,
            SetMethod setter,
            string declaringTypeName,
            MemberAccessibility memberAccessibility,
            MemberType memberType)
        {
            if (typeDef == null) throw new ArgumentNullException("typeDef");
            if (name == null) throw new ArgumentNullException("name");
            if (declaringTypeName == null) throw new ArgumentNullException("declaringTypeName");

            Name = name;
            FullName = declaringTypeName + "." + name;
            this.getter = getter;
            this.setter = setter;
            this.memberAccessibility = memberAccessibility;
            this.memberType = memberType;
            TypeDef = typeDef;

            SerializedName = name.IsAutoPropertyBackingField()
                ? name.AutoPropertyName()
                : name;
        }
 internal MemberDataBase(string name, MemberAccessibility accessibility, MemberFlags memberFlags)
 {
     this.Accessibility = accessibility;
     this.MemberFlags   = memberFlags;
     this.Name          = name;
 }
예제 #14
0
 internal IndexerData(string name, MemberAccessibility accessibility, MemberFlags memberFlags, TypeData type, bool isTypeDynamic, ParameterCollection parameters, MemberAccessibility?getMethodAccessibility, MemberAccessibility?setMethodAccessibility)
     : base(name, accessibility, memberFlags, type, isTypeDynamic, getMethodAccessibility, setMethodAccessibility)
 {
     this.Parameters = parameters;
 }
예제 #15
0
 internal EventData(string name, MemberAccessibility accessibility, MemberFlags memberFlags, TypeData type)
     : base(name, accessibility, memberFlags, type, isTypeDynamic: false)
 {
 }
 internal TypedMemberDataBase(string name, MemberAccessibility accessibility, MemberFlags memberFlags, TypeData type, bool isTypeDynamic)
     : base(name, accessibility, memberFlags)
 {
     this.Type          = type;
     this.IsTypeDynamic = isTypeDynamic;
 }
예제 #17
0
 private EventData(EventDefinition eventDefinition, MemberAccessibility accessibility, DeclaringTypeData declaringType)
     : base(eventDefinition, accessibility, eventDefinition.EventType, false, Utilities.GetMemberFlags(eventDefinition.AddMethod), declaringType)
 {
 }
      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);
      }
 internal PointerTypeData(string name, MemberAccessibility accessibility, MemberFlags memberFlags, TypeKind typeKind, TypeData elementType)
     : base(name, accessibility, memberFlags, typeKind, elementType)
 {
 }
      public ClassDeclarationSyntax GenerateProxyClass(SemanticModel semanticModel, SyntaxGenerator generator, INamedTypeSymbol sourceProxyInterface, string name, Accessibility accessibility, bool suppressWarningComments, MemberAccessibility constructorAccessibility, out IEnumerable<IMethodSymbol> sourceConstructors)
      {
         if (name == null)
         {
            if (sourceProxyInterface.Name.StartsWith("I"))
               name = sourceProxyInterface.Name.Substring(1) + "Proxy";
            else
               name = sourceProxyInterface.Name + "Proxy";
         }

         var compilation = semanticModel.Compilation;

         // Resolve the callback contract if any
         ITypeSymbol serviceContractAttributeType = compilation.RequireTypeByMetadataName("System.ServiceModel.ServiceContractAttribute");
         AttributeData serviceContractAttribute = sourceProxyInterface.GetAttributes().FirstOrDefault(attr => attr.AttributeClass.Equals(serviceContractAttributeType));
         if (serviceContractAttribute == null)
            throw new CodeGeneratorException(sourceProxyInterface, $"The interface {sourceProxyInterface.Name} is not decorated with ServiceContractAttribute.");

         ITypeSymbol callbackContractType;
         var callbackContractArg = serviceContractAttribute.NamedArguments.FirstOrDefault(arg => arg.Key.Equals("CallbackContract"));
         if (callbackContractArg.Key != null)
            callbackContractType = callbackContractArg.Value.Value as ITypeSymbol;
         else
            callbackContractType = null;

         // Resolve the base type (ClientBase or DuplexClientBase depending on whether a CallbackContract exists or not)
         INamedTypeSymbol baseType;
         if (callbackContractType != null)
         {
            baseType = compilation.RequireTypeByMetadataName("System.ServiceModel.DuplexClientBase`1").Construct(sourceProxyInterface);
         }
         else
         {
            baseType = compilation.RequireTypeByMetadataName("System.ServiceModel.ClientBase`1").Construct(sourceProxyInterface);
         }

         // Create class declaration
         SyntaxNode targetClass = generator.ClassDeclaration(name, accessibility: accessibility, baseType: generator.TypeExpression(baseType), interfaceTypes: new[] { generator.TypeExpression(sourceProxyInterface) });

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


         // Copy constructors from base class.
         sourceConstructors = baseType.Constructors.Where(ctor => ctor.DeclaredAccessibility != Accessibility.Private).ToImmutableArray();

         foreach (var baseCtor in sourceConstructors)
         {
            var targetCtor = generator.ConstructorDeclaration(baseCtor, baseCtor.Parameters.Select(p => generator.Argument(generator.IdentifierName(p.Name))));

            targetCtor = generator.AddWarningCommentIf(!suppressWarningComments, targetCtor);

            targetCtor = generator.WithAccessibility(targetCtor, ToAccessibility(constructorAccessibility));
            targetClass = generator.AddMembers(targetClass, targetCtor.AddNewLineTrivia());
         }

         foreach (IMethodSymbol sourceMethod in GetOperationContractMethods(semanticModel.Compilation, sourceProxyInterface))
         {
            SyntaxNode targetMethod = generator.MethodDeclaration(sourceMethod);

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

            targetMethod = generator.WithModifiers(targetMethod, DeclarationModifiers.None);

            bool isVoid = sourceMethod.ReturnType.SpecialType == SpecialType.System_Void;
            targetMethod = targetMethod.AddNewLineTrivia().AddNewLineTrivia();

            var expression = generator.InvocationExpression(
               generator.MemberAccessExpression(
                  generator.MemberAccessExpression(
                     generator.BaseExpression(),
                     "Channel"
                  ),
                  sourceMethod.Name
               ),
               sourceMethod.Parameters.Select(p => generator.IdentifierName(p.Name)).ToArray()
            );

            SyntaxNode statement;
            if (!isVoid)
               statement = generator.ReturnStatement(expression);
            else
               statement = generator.ExpressionStatement(expression);

            targetMethod = generator.WithStatements(targetMethod,
               new[]
               {
                  statement
               }
            );
            targetClass = generator.AddMembers(targetClass, targetMethod.AddNewLineTrivia());
         }

         return (ClassDeclarationSyntax)targetClass;
      }
예제 #21
0
 private ConstructorData(MethodDefinition methodDefinition, MemberAccessibility accessibility, DeclaringTypeData declaringType)
     : base(methodDefinition, accessibility, Utilities.GetMemberFlags(methodDefinition), declaringType)
 {
     this.Parameters = new ParameterCollection(methodDefinition.Parameters, this);
 }
예제 #22
0
 internal TypeData(string name, MemberAccessibility accessibility, MemberFlags memberFlags, TypeKind typeKind)
     : base(name, accessibility, memberFlags)
 {
     this.TypeKind = typeKind;
 }
예제 #23
0
 internal TypeData(TypeReference type, MemberAccessibility accessibility, DeclaringTypeData declaringType)
     : base(type, accessibility, Utilities.GetMemberFlags(type), declaringType)
 {
     this.TypeKind = Utilities.GetTypeKind(type);
 }
예제 #24
0
 internal MethodData(string name, MemberAccessibility accessibility, MemberFlags memberFlags, TypeData type, bool isTypeDynamic, GenericTypeParameterCollection genericParameters, bool isExtensionMethod, ParameterCollection parameters)
     : base(name, accessibility, memberFlags, type, isTypeDynamic, parameters)
 {
     this.GenericParameters = genericParameters;
     this.IsExtensionMethod = isExtensionMethod;
 }
 internal PropertyData(string name, MemberAccessibility accessibility, MemberFlags memberFlags, TypeData type, bool isTypeDynamic, MemberAccessibility?getMethodAccessibility, MemberAccessibility?setMethodAccessibility)
     : base(name, accessibility, memberFlags, type, isTypeDynamic)
 {
     this.GetMethodAccessibility = getMethodAccessibility;
     this.SetMethodAccessibility = setMethodAccessibility;
 }
예제 #26
0
 internal ArrayTypeData(string name, MemberAccessibility accessibility, MemberFlags memberFlags, TypeKind typeKind, TypeData elementType, byte arrayRank)
     : base(name, accessibility, memberFlags, typeKind, elementType)
 {
     this.ArrayRank = arrayRank;
 }
예제 #27
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));
        }
예제 #28
0
 internal DeclaringTypeData(string name, MemberAccessibility accessibility, MemberFlags memberFlags, TypeKind typeKind)
     : base(name, accessibility, memberFlags, typeKind)
 {
     _membersByName = new Dictionary <string, List <MemberDataBase> >();
 }
예제 #29
0
 internal ConstructorData(string name, MemberAccessibility accessibility, MemberFlags memberFlags, ParameterCollection parameters)
     : base(name, accessibility, memberFlags)
 {
     this.Parameters = parameters;
 }
예제 #30
0
 internal DeclaringTypeData(TypeReference type, MemberAccessibility accessibility, DeclaringTypeData declaringType)
     : base(type, accessibility, declaringType)
 {
     _membersByName = new Dictionary <string, List <MemberDataBase> >();
 }
예제 #31
0
 public extern ReflectableAttribute(MemberAccessibility memberAccessibility);
 private static void AccessibilityMatches(MemberAccessibility memberAccessibility, MemberAccessibility requiredAccessibility, bool expected)
 {
     DefaultPropertyDefinition sut = CreatePropertyDefinition(memberAccessibility, MemberType.Property);
     sut.MatchesPropertyFilter(new ObjectParsingOptions { MemberAccessibility = requiredAccessibility, MemberType = MemberType.Property })
         .ShouldBe(expected);
 }
 private static DefaultPropertyDefinition CreatePropertyDefinition(MemberAccessibility memberAccessibility, MemberType memberType)
 {
     return new DefaultPropertyDefinition(Substitute.For<TypeDefinition>(typeof(object)), string.Empty, null, null, string.Empty, memberAccessibility, memberType);
 }
예제 #34
0
 internal TypeWithElementData(string name, MemberAccessibility accessibility, MemberFlags memberFlags, TypeKind typeKind, TypeData elementType)
     : base(name, accessibility, memberFlags, typeKind)
 {
     this.ElementType = elementType;
 }
        public ClassDeclarationSyntax GenerateProxyClass(SemanticModel semanticModel, SyntaxGenerator generator, INamedTypeSymbol sourceProxyInterface, string name, Accessibility accessibility, bool suppressWarningComments, MemberAccessibility constructorAccessibility, out IEnumerable <IMethodSymbol> sourceConstructors)
        {
            if (name == null)
            {
                if (sourceProxyInterface.Name.StartsWith("I"))
                {
                    name = sourceProxyInterface.Name.Substring(1) + "Proxy";
                }
                else
                {
                    name = sourceProxyInterface.Name + "Proxy";
                }
            }

            var compilation = semanticModel.Compilation;

            // Resolve the callback contract if any
            ITypeSymbol   serviceContractAttributeType = compilation.RequireTypeByMetadataName("System.ServiceModel.ServiceContractAttribute");
            AttributeData serviceContractAttribute     = sourceProxyInterface.GetAttributes().FirstOrDefault(attr => attr.AttributeClass.Equals(serviceContractAttributeType));

            if (serviceContractAttribute == null)
            {
                throw new CodeGeneratorException(sourceProxyInterface, $"The interface {sourceProxyInterface.Name} is not decorated with ServiceContractAttribute.");
            }

            ITypeSymbol callbackContractType;
            var         callbackContractArg = serviceContractAttribute.NamedArguments.FirstOrDefault(arg => arg.Key.Equals("CallbackContract"));

            if (callbackContractArg.Key != null)
            {
                callbackContractType = callbackContractArg.Value.Value as ITypeSymbol;
            }
            else
            {
                callbackContractType = null;
            }

            // Resolve the base type (ClientBase or DuplexClientBase depending on whether a CallbackContract exists or not)
            INamedTypeSymbol baseType;

            if (callbackContractType != null)
            {
                baseType = compilation.RequireTypeByMetadataName("System.ServiceModel.DuplexClientBase`1").Construct(sourceProxyInterface);
            }
            else
            {
                baseType = compilation.RequireTypeByMetadataName("System.ServiceModel.ClientBase`1").Construct(sourceProxyInterface);
            }

            // Create class declaration
            SyntaxNode targetClass = generator.ClassDeclaration(name, accessibility: accessibility, baseType: generator.TypeExpression(baseType), interfaceTypes: new[] { generator.TypeExpression(sourceProxyInterface) });

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


            // Copy constructors from base class.
            sourceConstructors = baseType.Constructors.Where(ctor => ctor.DeclaredAccessibility != Accessibility.Private).ToImmutableArray();

            foreach (var baseCtor in sourceConstructors)
            {
                var targetCtor = generator.ConstructorDeclaration(baseCtor, baseCtor.Parameters.Select(p => generator.Argument(generator.IdentifierName(p.Name))));

                targetCtor = generator.AddWarningCommentIf(!suppressWarningComments, targetCtor);

                targetCtor  = generator.WithAccessibility(targetCtor, ToAccessibility(constructorAccessibility));
                targetClass = generator.AddMembers(targetClass, targetCtor.AddNewLineTrivia());
            }

            foreach (IMethodSymbol sourceMethod in GetOperationContractMethods(semanticModel.Compilation, sourceProxyInterface))
            {
                SyntaxNode targetMethod = generator.MethodDeclaration(sourceMethod);

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

                targetMethod = generator.WithModifiers(targetMethod, DeclarationModifiers.None);

                bool isVoid = sourceMethod.ReturnType.SpecialType == SpecialType.System_Void;
                targetMethod = targetMethod.AddNewLineTrivia().AddNewLineTrivia();

                var expression = generator.InvocationExpression(
                    generator.MemberAccessExpression(
                        generator.MemberAccessExpression(
                            generator.BaseExpression(),
                            "Channel"
                            ),
                        sourceMethod.Name
                        ),
                    sourceMethod.Parameters.Select(p => generator.IdentifierName(p.Name)).ToArray()
                    );

                SyntaxNode statement;
                if (!isVoid)
                {
                    statement = generator.ReturnStatement(expression);
                }
                else
                {
                    statement = generator.ExpressionStatement(expression);
                }

                targetMethod = generator.WithStatements(targetMethod,
                                                        new[]
                {
                    statement
                }
                                                        );
                targetClass = generator.AddMembers(targetClass, targetMethod.AddNewLineTrivia());
            }

            return((ClassDeclarationSyntax)targetClass);
        }
      private static Accessibility ToAccessibility(MemberAccessibility accessibility)
      {
         switch (accessibility)
         {
            case MemberAccessibility.Public:
               return Accessibility.Public;

            case MemberAccessibility.Protected:
               return Accessibility.Protected;

            case MemberAccessibility.Internal:
               return Accessibility.Internal;

            case MemberAccessibility.Private:
               return Accessibility.Private;

            case MemberAccessibility.ProtectedInternal:
               return Accessibility.ProtectedOrInternal;

            default:
               throw new NotSupportedException($"Invalid accessibility {accessibility}.");
         }
      }