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); }
/// <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)); }
public static object GetAttribute(this IMethodSymbol symbol, Type type, bool doNotTraverseHierarchy = false) { return(symbol.GetAttribute(type, MemberTypes.Method)); }