Ejemplo n.º 1
0
        /// <summary>
        /// Creates and returns a map from interface id to intercepted invoker for non-generic or open-generic types.
        /// </summary>
        /// <param name="implementationType">The implementation type.</param>
        /// <param name="invoker">The underlying invoker.</param>
        /// <returns>A map from interface id to intercepted invoker.</returns>
        private static Dictionary <int, InterceptedMethodInvoker> CreateMapForNonGeneric(Type implementationType, IGrainMethodInvoker invoker)
        {
            if (implementationType.IsConstructedGenericType)
            {
                throw new InvalidOperationException(
                          $"Type {implementationType} passed to {nameof(CreateMapForNonGeneric)} is a constructed generic type.");
            }

            var implementationTypeInfo = implementationType.GetTypeInfo();
            var interfaces             = implementationType.GetInterfaces();

            // Create an invoker for every interface on the provided type.
            var result = new Dictionary <int, InterceptedMethodInvoker>(interfaces.Length);

            foreach (var iface in interfaces)
            {
                var methods = GrainInterfaceUtils.GetMethods(iface);

                // Map every method on this interface from the definition interface onto the implementation class.
                var methodMap = new Dictionary <int, MethodInfo>(methods.Length);
                var mapping   = default(InterfaceMapping);
                foreach (var method in methods)
                {
                    // If this method is not from the expected interface (eg, because it's from a parent interface), then
                    // get the mapping for the interface which it does belong to.
                    if (mapping.InterfaceType != method.DeclaringType)
                    {
                        mapping = implementationTypeInfo.GetRuntimeInterfaceMap(method.DeclaringType);
                    }

                    // Find the index of the interface method and then get the implementation method at that position.
                    for (var k = 0; k < mapping.InterfaceMethods.Length; k++)
                    {
                        if (mapping.InterfaceMethods[k] != method)
                        {
                            continue;
                        }
                        methodMap[GrainInterfaceUtils.ComputeMethodId(method)] = mapping.TargetMethods[k];
                        break;
                    }
                }

                // Add the resulting map of methodId -> method to the interface map.
                var interfaceId = GrainInterfaceUtils.GetGrainInterfaceId(iface);
                result[interfaceId] = new InterceptedMethodInvoker(invoker, methodMap);
            }

            return(result);
        }
        /// <summary>
        /// Creates and returns a map from interface id to intercepted invoker for non-generic or open-generic types.
        /// </summary>
        /// <param name="implementationType">The implementation type.</param>
        /// <param name="invoker">The underlying invoker.</param>
        /// <returns>A map from interface id to intercepted invoker.</returns>
        private static Dictionary<int, InterceptedMethodInvoker> CreateMapForNonGeneric(Type implementationType, IGrainMethodInvoker invoker)
        {
            if (implementationType.IsConstructedGenericType)
            {
                throw new InvalidOperationException(
                    $"Type {implementationType} passed to {nameof(CreateMapForNonGeneric)} is a constructed generic type.");
            }

            var implementationTypeInfo = implementationType.GetTypeInfo();
            var interfaces = implementationType.GetInterfaces();

            // Create an invoker for every interface on the provided type.
            var result = new Dictionary<int, InterceptedMethodInvoker>(interfaces.Length);
            foreach (var iface in interfaces)
            {
                var methods = GrainInterfaceUtils.GetMethods(iface);

                // Map every method on this interface from the definition interface onto the implementation class.
                var methodMap = new Dictionary<int, MethodInfo>(methods.Length);
                var mapping = default(InterfaceMapping);
                foreach (var method in methods)
                {
                    // If this method is not from the expected interface (eg, because it's from a parent interface), then
                    // get the mapping for the interface which it does belong to.
                    if (mapping.InterfaceType != method.DeclaringType)
                    {
                        mapping = implementationTypeInfo.GetRuntimeInterfaceMap(method.DeclaringType);
                    }

                    // Find the index of the interface method and then get the implementation method at that position.
                    for (var k = 0; k < mapping.InterfaceMethods.Length; k++)
                    {
                        if (mapping.InterfaceMethods[k] != method) continue;
                        methodMap[GrainInterfaceUtils.ComputeMethodId(method)] = mapping.TargetMethods[k];
                        break;
                    }
                }

                // Add the resulting map of methodId -> method to the interface map.
                var interfaceId = GrainInterfaceUtils.GetGrainInterfaceId(iface);
                result[interfaceId] = new InterceptedMethodInvoker(invoker, methodMap);
            }

            return result;
        }
        /// <summary>
        /// Creates and returns a map from interface id to intercepted invoker for constructed generic types.
        /// </summary>
        /// <param name="implementationType">The implementation type.</param>
        /// <param name="invoker">The underlying invoker.</param>
        /// <returns>A map from interface id to intercepted invoker.</returns>
        private static Dictionary<int, InterceptedMethodInvoker> CreateMapForConstructedGeneric(
            Type implementationType,
            IGrainMethodInvoker invoker)
        {
            // It is important to note that the interfaceId and methodId are computed based upon the non-concrete
            // version of the implementation type. During code generation, the concrete type would not be available
            // and therefore the generic type definition is used.
            if (!implementationType.IsConstructedGenericType)
            {
                throw new InvalidOperationException(
                    $"Type {implementationType} passed to {nameof(CreateMapForConstructedGeneric)} is not a constructed generic type");
            }

            var genericClass = implementationType.GetGenericTypeDefinition();
            var genericClassTypeInfo = genericClass.GetTypeInfo();
            var implementationTypeInfo = implementationType.GetTypeInfo();

            var genericInterfaces = genericClass.GetInterfaces();
            var concreteInterfaces = implementationType.GetInterfaces();

            // Create an invoker for every interface on the provided type.
            var result = new Dictionary<int, InterceptedMethodInvoker>(genericInterfaces.Length);
            for (var i = 0; i < genericInterfaces.Length; i++)
            {
                // Because these methods are identical except for type parameters, their methods should also be identical except
                // for type parameters, including identical ordering. That is the assumption.
                var genericMethods = GrainInterfaceUtils.GetMethods(genericInterfaces[i]);
                var concreteInterfaceMethods = GrainInterfaceUtils.GetMethods(concreteInterfaces[i]);

                // Map every method on this interface from the definition interface onto the implementation class.
                var methodMap = new Dictionary<int, MethodInfo>(genericMethods.Length);
                var genericMap = default(InterfaceMapping);
                var concreteMap = default(InterfaceMapping);
                for (var j = 0; j < genericMethods.Length; j++)
                {
                    // If this method is not from the expected interface (eg, because it's from a parent interface), then
                    // get the mapping for the interface which it does belong to.
                    var genericInterfaceMethod = genericMethods[j];
                    if (genericMap.InterfaceType != genericInterfaceMethod.DeclaringType)
                    {
                        genericMap = genericClassTypeInfo.GetRuntimeInterfaceMap(genericInterfaceMethod.DeclaringType);
                        concreteMap = implementationTypeInfo.GetRuntimeInterfaceMap(concreteInterfaceMethods[j].DeclaringType);
                    }

                    // Determine the position in the definition's map which the target method belongs to and take the implementation
                    // from the same position on the implementation's map.
                    for (var k = 0; k < genericMap.InterfaceMethods.Length; k++)
                    {
                        if (genericMap.InterfaceMethods[k] != genericInterfaceMethod) continue;
                        methodMap[GrainInterfaceUtils.ComputeMethodId(genericInterfaceMethod)] = concreteMap.TargetMethods[k];
                        break;
                    }
                }

                // Add the resulting map of methodId -> method to the interface map.
                var interfaceId = GrainInterfaceUtils.GetGrainInterfaceId(genericInterfaces[i]);
                result[interfaceId] = new InterceptedMethodInvoker(invoker, methodMap);
            }

            return result;
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Creates and returns a map from interface id to intercepted invoker for constructed generic types.
        /// </summary>
        /// <param name="implementationType">The implementation type.</param>
        /// <param name="invoker">The underlying invoker.</param>
        /// <returns>A map from interface id to intercepted invoker.</returns>
        private static Dictionary <int, InterceptedMethodInvoker> CreateMapForConstructedGeneric(
            Type implementationType,
            IGrainMethodInvoker invoker)
        {
            // It is important to note that the interfaceId and methodId are computed based upon the non-concrete
            // version of the implementation type. During code generation, the concrete type would not be available
            // and therefore the generic type definition is used.
            if (!implementationType.IsConstructedGenericType)
            {
                throw new InvalidOperationException(
                          $"Type {implementationType} passed to {nameof(CreateMapForConstructedGeneric)} is not a constructed generic type");
            }

            var genericClass           = implementationType.GetGenericTypeDefinition();
            var genericClassTypeInfo   = genericClass.GetTypeInfo();
            var implementationTypeInfo = implementationType.GetTypeInfo();

            var genericInterfaces  = genericClass.GetInterfaces();
            var concreteInterfaces = implementationType.GetInterfaces();

            // Create an invoker for every interface on the provided type.
            var result = new Dictionary <int, InterceptedMethodInvoker>(genericInterfaces.Length);

            for (var i = 0; i < genericInterfaces.Length; i++)
            {
                // Because these methods are identical except for type parameters, their methods should also be identical except
                // for type parameters, including identical ordering. That is the assumption.
                var genericMethods           = GrainInterfaceUtils.GetMethods(genericInterfaces[i]);
                var concreteInterfaceMethods = GrainInterfaceUtils.GetMethods(concreteInterfaces[i]);

                // Map every method on this interface from the definition interface onto the implementation class.
                var methodMap   = new Dictionary <int, MethodInfo>(genericMethods.Length);
                var genericMap  = default(InterfaceMapping);
                var concreteMap = default(InterfaceMapping);
                for (var j = 0; j < genericMethods.Length; j++)
                {
                    // If this method is not from the expected interface (eg, because it's from a parent interface), then
                    // get the mapping for the interface which it does belong to.
                    var genericInterfaceMethod = genericMethods[j];
                    if (genericMap.InterfaceType != genericInterfaceMethod.DeclaringType)
                    {
                        genericMap  = genericClassTypeInfo.GetRuntimeInterfaceMap(genericInterfaceMethod.DeclaringType);
                        concreteMap = implementationTypeInfo.GetRuntimeInterfaceMap(concreteInterfaceMethods[j].DeclaringType);
                    }

                    // Determine the position in the definition's map which the target method belongs to and take the implementation
                    // from the same position on the implementation's map.
                    for (var k = 0; k < genericMap.InterfaceMethods.Length; k++)
                    {
                        if (genericMap.InterfaceMethods[k] != genericInterfaceMethod)
                        {
                            continue;
                        }
                        methodMap[GrainInterfaceUtils.ComputeMethodId(genericInterfaceMethod)] = concreteMap.TargetMethods[k];
                        break;
                    }
                }

                // Add the resulting map of methodId -> method to the interface map.
                var interfaceId = GrainInterfaceUtils.GetGrainInterfaceId(genericInterfaces[i]);
                result[interfaceId] = new InterceptedMethodInvoker(invoker, methodMap);
            }

            return(result);
        }