public void Generic_InterfaceId_Test() { var expected = GrainInterfaceUtils.GetGrainInterfaceId(typeof(ISimpleGenericGrain <>)); IDictionary <int, Type> actual = GrainInterfaceUtils.GetRemoteInterfaces(typeof(SimpleGenericGrain <>)); Assert.Contains(expected, actual); }
public void Generic_InterfaceId_Test() { var expected = GrainInterfaceUtils.GetGrainInterfaceId(typeof(ISimpleGenericGrain <>)); var actual = GrainInterfaceUtils.GetRemoteInterfaces(typeof(SimpleGenericGrain <>)); Assert.Single(actual); Assert.Equal(expected, GrainInterfaceUtils.GetGrainInterfaceId(actual[0])); }
private IGrainExtensionMethodInvoker TryGetExtensionInvoker(Type handlerType) { var interfaces = GrainInterfaceUtils.GetRemoteInterfaces(handlerType).Values; if (interfaces.Count != 1) throw new InvalidOperationException($"Extension type {handlerType.FullName} implements more than one grain interface."); var interfaceId = GrainInterfaceUtils.GetGrainInterfaceId(interfaces.First()); var invoker = typeManager.GetInvoker(interfaceId); if (invoker != null) return (IGrainExtensionMethodInvoker)invoker; throw new ArgumentException( $"Provider extension handler type {handlerType} was not found in the type manager", nameof(handlerType)); }
/// <summary> /// Maps the provided <paramref name="interfaceId"/> to the provided <paramref name="implementationType"/>. /// </summary> /// <param name="interfaceType">The interface type.</param> /// <param name="implementationType">The implementation type.</param> /// <returns>The mapped interface.</returns> private static IReadOnlyDictionary <int, MethodInfo> GetInterfaceToImplementationMap( int interfaceId, Type implementationType) { // Get the interface mapping for the current implementation. var interfaceTypes = GrainInterfaceUtils.GetRemoteInterfaces(implementationType); var interfaceType = interfaceTypes[interfaceId]; var interfaceMapping = implementationType.GetInterfaceMap(interfaceType); // Map the interface methods to implementation methods. var interfaceMethods = GrainInterfaceUtils.GetMethods(interfaceType); return(interfaceMethods.ToDictionary( GrainInterfaceUtils.ComputeMethodId, interfaceMethod => GetImplementingMethod(interfaceMethod, interfaceMapping))); }
/// <summary> /// Maps the provided <paramref name="interfaceId"/> to the provided <paramref name="implementationType"/>. /// </summary> /// <param name="interfaceId">The interface id.</param> /// <param name="implementationType">The implementation type.</param> /// <returns>The mapped interface.</returns> private static Dictionary <int, MethodInfo> GetInterfaceToImplementationMap( int interfaceId, Type implementationType) { var interfaceTypes = GrainInterfaceUtils.GetRemoteInterfaces(implementationType); // Get all interface mappings of all interfaces. var interfaceMapping = implementationType .GetInterfaces() .Select(i => implementationType.GetTypeInfo().GetRuntimeInterfaceMap(i)) .SelectMany(map => map.InterfaceMethods .Zip(map.TargetMethods, (interfaceMethod, targetMethod) => new { interfaceMethod, targetMethod })) .ToArray(); // Map the grain interface methods to the implementation methods. return(GrainInterfaceUtils.GetMethods(interfaceTypes[interfaceId]) .ToDictionary(GrainInterfaceUtils.ComputeMethodId, m => interfaceMapping.SingleOrDefault(pair => pair.interfaceMethod == m)?.targetMethod)); }
/// <summary> /// Generates switch cases for the provided grain type. /// </summary> /// <param name="grainType"> /// The grain type. /// </param> /// <param name="methodIdArgument"> /// The method id argument, which is used to select the correct switch label. /// </param> /// <param name="generateMethodHandler"> /// The function used to generate switch block statements for each method. /// </param> /// <returns> /// The switch cases for the provided grain type. /// </returns> public static SwitchSectionSyntax[] GenerateGrainInterfaceAndMethodSwitch( Type grainType, ExpressionSyntax methodIdArgument, Func <MethodInfo, StatementSyntax[]> generateMethodHandler) { var interfaces = GrainInterfaceUtils.GetRemoteInterfaces(grainType); interfaces[GrainInterfaceUtils.GetGrainInterfaceId(grainType)] = grainType; // Switch on interface id. var interfaceCases = new List <SwitchSectionSyntax>(); foreach (var @interface in interfaces) { var interfaceType = @interface.Value; var interfaceId = @interface.Key; var methods = GrainInterfaceUtils.GetMethods(interfaceType); var methodCases = new List <SwitchSectionSyntax>(); // Switch on method id. foreach (var method in methods) { // Generate switch case. var methodId = GrainInterfaceUtils.ComputeMethodId(method); var methodType = method; // Generate the switch label for this interface id. var methodIdSwitchLabel = SF.CaseSwitchLabel( SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(methodId))); // Generate the switch body. var methodInvokeStatement = generateMethodHandler(methodType); methodCases.Add( SF.SwitchSection().AddLabels(methodIdSwitchLabel).AddStatements(methodInvokeStatement)); } // Generate the switch label for this interface id. var interfaceIdSwitchLabel = SF.CaseSwitchLabel( SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(interfaceId))); // Generate the default case, which will throw a NotImplementedException. var errorMessage = SF.BinaryExpression( SyntaxKind.AddExpression, "interfaceId=".GetLiteralExpression(), SF.BinaryExpression( SyntaxKind.AddExpression, SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(interfaceId)), SF.BinaryExpression( SyntaxKind.AddExpression, ",methodId=".GetLiteralExpression(), methodIdArgument))); var throwStatement = SF.ThrowStatement( SF.ObjectCreationExpression(typeof(NotImplementedException).GetTypeSyntax()) .AddArgumentListArguments(SF.Argument(errorMessage))); var defaultCase = SF.SwitchSection().AddLabels(SF.DefaultSwitchLabel()).AddStatements(throwStatement); // Generate switch statements for the methods in this interface. var methodSwitchStatements = SF.SwitchStatement(methodIdArgument).AddSections(methodCases.ToArray()).AddSections(defaultCase); // Generate the switch section for this interface. interfaceCases.Add( SF.SwitchSection().AddLabels(interfaceIdSwitchLabel).AddStatements(methodSwitchStatements)); } return(interfaceCases.ToArray()); }