public OperationContractMethodInfo(SemanticModel semanticModel, IMethodSymbol method)
            {
                var taskType        = semanticModel.Compilation.RequireTypeByMetadataName(typeof(Task).FullName);
                var genericTaskType = semanticModel.Compilation.RequireTypeByMetadataName(typeof(Task <>).FullName);
                var operationContractAttributeType = semanticModel.Compilation.RequireTypeByMetadataName("System.ServiceModel.OperationContractAttribute");
                var faultContractAttributeType     = semanticModel.Compilation.RequireTypeByMetadataName("System.ServiceModel.FaultContractAttribute");

                var operationContractAttribute = method.GetAttribute(operationContractAttributeType);

                if (operationContractAttribute == null)
                {
                    throw new InvalidOperationException($"The method {method.Name} is not decorated with {operationContractAttributeType.GetFullName()}.");
                }

                OperationContractAttribute = new ModifiedOperationContractAttributeData(operationContractAttribute);

                FaultContractAttributes = method.GetAttributes().Where(attr => attr.AttributeClass.Equals(faultContractAttributeType)).ToImmutableArray();

                AdditionalAttributes = method.GetAttributes()
                                       .Where(
                    attr => !attr.AttributeClass.Equals(operationContractAttributeType) &&
                    !attr.AttributeClass.Equals(faultContractAttributeType)
                    ).ToImmutableArray();

                IsAsync = method.ReturnType.Equals(taskType) || method.ReturnType.OriginalDefinition.Equals(genericTaskType.OriginalDefinition);

                ContractReturnsVoid = method.ReturnsVoid || method.ReturnType.Equals(taskType);

                Method = method;

                if (IsAsync && method.Name.EndsWith("Async"))
                {
                    ContractMethodName = method.Name.Substring(0, method.Name.Length - "Async".Length);
                }
                else
                {
                    ContractMethodName = method.Name;
                }

                if (IsAsync)
                {
                    if (ContractReturnsVoid)
                    {
                        ContractReturnType = semanticModel.Compilation.GetSpecialType(SpecialType.System_Void);
                    }
                    else
                    {
                        ContractReturnType = ((INamedTypeSymbol)method.ReturnType).TypeArguments.Single();
                    }
                }
                else
                {
                    ContractReturnType = ReturnType;
                }

                AsyncReturnType = ContractReturnsVoid ? taskType : genericTaskType.Construct(ContractReturnType);
            }
        public static AttributeData TryGetDerivedAttribute(this IMethodSymbol symbol, Func <AttributeData, bool> condition)
        {
            while (symbol != null)
            {
                var attr = symbol.GetAttribute(condition);
                if (attr != null)
                {
                    return(attr);
                }

                if (symbol.OverriddenMethod == null)
                {
                    return(null);
                }

                symbol = symbol.OverriddenMethod;
            }

            return(null);
        }
Example #3
0
        /// <summary>
        /// Returns syntax for the options argument to GrainReference.InvokeMethodAsync{T} and GrainReference.InvokeOneWayMethod.
        /// </summary>
        private static ArgumentSyntax GetInvokeOptions(WellKnownTypes wellKnownTypes, IMethodSymbol method)
        {
            var options = new List <ExpressionSyntax>();
            var imo     = wellKnownTypes.InvokeMethodOptions.ToNameSyntax();

            if (method.HasAttribute(wellKnownTypes.ReadOnlyAttribute))
            {
                options.Add(imo.Member("ReadOnly"));
            }

            if (method.HasAttribute(wellKnownTypes.UnorderedAttribute))
            {
                options.Add(imo.Member("Unordered"));
            }

            if (method.HasAttribute(wellKnownTypes.AlwaysInterleaveAttribute))
            {
                options.Add(imo.Member("AlwaysInterleave"));
            }

            if (method.GetAttribute(wellKnownTypes.TransactionAttribute, out var attr))
            {
                var enumType      = wellKnownTypes.TransactionOption;
                var txRequirement = (int)attr.ConstructorArguments.First().Value;
                var values        = enumType.GetMembers().OfType <IFieldSymbol>().ToList();
                var mapping       = values.ToDictionary(m => (int)m.ConstantValue, m => m.Name);
                if (!mapping.TryGetValue(txRequirement, out var value))
                {
                    throw new NotSupportedException($"Transaction requirement {txRequirement} on method {method} was not understood.");
                }

                switch (value)
                {
                case "Suppress":
                    options.Add(imo.Member("TransactionSuppress"));
                    break;

                case "CreateOrJoin":
                    options.Add(imo.Member("TransactionCreateOrJoin"));
                    break;

                case "Create":
                    options.Add(imo.Member("TransactionCreate"));
                    break;

                case "Join":
                    options.Add(imo.Member("TransactionJoin"));
                    break;

                case "Supported":
                    options.Add(imo.Member("TransactionSupported"));
                    break;

                case "NotAllowed":
                    options.Add(imo.Member("TransactionNotAllowed"));
                    break;

                default:
                    throw new NotSupportedException($"Transaction requirement {value} on method {method} was not understood.");
                }
            }

            ExpressionSyntax allOptions;

            if (options.Count <= 1)
            {
                allOptions = options.FirstOrDefault();
            }
            else
            {
                allOptions =
                    options.Aggregate((a, b) => BinaryExpression(SyntaxKind.BitwiseOrExpression, a, b));
            }

            if (allOptions == null)
            {
                return(null);
            }

            return(Argument(NameColon("options"), Token(SyntaxKind.None), allOptions));
        }
Example #4
0
 public static object GetAttribute(this IMethodSymbol symbol, Type type, bool doNotTraverseHierarchy = false)
 {
     return(symbol.GetAttribute(type, MemberTypes.Method));
 }