예제 #1
0
        //
        // MakeGenericMethod
        //

        public override MethodInfo MakeGenericMethod(Type[] typeArguments)
        {
            if (!IsGenericMethodDefinition)
            {
                throw new InvalidOperationException();
            }
            if (typeArguments == null)
            {
                throw new ArgumentNullException();
            }

            var implicitTypeArgs      = reflectedType.GetGenericArguments();
            int implicitTypeArgsCount = implicitTypeArgs.Length;
            var explicitTypeArgsCount = typeArguments.Length;
            int combinedTypeArgsCount = implicitTypeArgsCount + explicitTypeArgsCount;

            var combinedTypeArgs = new object[combinedTypeArgsCount];

            java.lang.System.arraycopy(
                /* from  */ implicitTypeArgs, 0,
                /* into  */ combinedTypeArgs, 0,
                /* count */ implicitTypeArgsCount);
            java.lang.System.arraycopy(
                /* from */ typeArguments, 0,
                /* into */ combinedTypeArgs, implicitTypeArgsCount,
                /* count */ explicitTypeArgsCount);

            var newMethod = new RuntimeMethodInfo(JavaMethod, -1, reflectedType,
                                                  originalName, strippedName);

            newMethod.typeArguments = combinedTypeArgs;
            newMethod.genericFlags  = flgGenericMethod;

            for (int i = 0; i < combinedTypeArgsCount; i++)
            {
                var arg = combinedTypeArgs[i] as RuntimeType;
                if (arg == null)
                {
                    throw new ArgumentNullException();
                }
                if (arg.IsGenericParameter || arg.ContainsGenericParameters)
                {
                    newMethod.genericFlags |= flgContainsGenericParameters;
                }
            }

            return(newMethod);
        }
예제 #2
0
        //
        // constructor
        //

        #pragma warning disable 0436
        private RuntimeMethodInfo(java.lang.reflect.Method javaMethod, int modifiers,
                                  system.RuntimeType reflectedType,
                                  string originalName, string strippedName)
        #pragma warning restore 0436
        {
            this.JavaMethod    = javaMethod;
            this.reflectedType = reflectedType;
            this.originalName  = originalName;
            this.strippedName  = strippedName;

            if (modifiers == -1)    // if called from MakeGenericMethod
            {
                return;
            }

            // analyze the method and the declaring type in order to decide what
            // type of a generic method this is.  the general idea is:
            // if the method takes more generic parameters, than the number of
            // arguments in the type, then it is a generic method definition.

            int  originalNameLen = originalName.Length;
            char lastChar        = (originalNameLen > 0)
                          ? originalName[originalNameLen - 1]
                          : (char)0;

            // the actual suffix character is configured in CilMain.cs
            if (lastChar == '\u00A1' || lastChar == '!') // U+00A1 Inverted Exclamation Mark
            {
                if ((modifiers & java.lang.reflect.Modifier.STATIC) == 0)
                {
                    // if an instance method takes any type arguments at all,
                    // then it must be a generic method definition
                    genericFlags |= flgGenericMethod
                                    | flgGenericMethodDefinition
                                    | flgContainsGenericParameters;
                }
                else
                {
                    // count the number of type arguments in the declaring type
                    var typeArgsInType    = reflectedType.GetGenericArguments();
                    int numTypeArgsInType = typeArgsInType.Length;

                    // count the number of type parameters in the method signature
                    int numTypeArgsInMethod = 0;
                    var paramTypes          = javaMethod.getParameterTypes();
                    int paramIndex          = paramTypes.Length;
                    while (paramIndex-- > 0)
                    {
                        var paramType = paramTypes[paramIndex];
                        if (paramType != (java.lang.Class) typeof(System.Type))
                        {
                            break;
                        }
                        numTypeArgsInMethod++;
                    }

                    if (numTypeArgsInMethod == numTypeArgsInType)
                    {
                        // a static method that takes a number of type parameters
                        // equal to the number of arguments in the declaring type.
                        // this means it is not a generic method, but it may not
                        // be invokable, if the declaring type is not concrete.

                        if (reflectedType.ContainsGenericParameters)
                        {
                            genericFlags |= flgContainsGenericParameters;
                        }

                        else if (reflectedType.IsGenericType)
                        {
                            genericFlags |= flgCombineGenericArguments;
                        }
                    }

                    else if (numTypeArgsInMethod > numTypeArgsInType)
                    {
                        // a static method that takes more parameters than the
                        // declaring type, i.e. it is a generic method definition.
                        genericFlags |= flgGenericMethod
                                        | flgGenericMethodDefinition
                                        | flgContainsGenericParameters;
                    }

                    else
                    {
                        throw new TypeLoadException(originalName);
                    }
                }
            }
            else
            {
                // a method that does not take any type argument may still be
                // not invokable, if the reflected type is not a concrete type.
                // note that this is true only for instance methods, as static
                // methods in a generic type will always take type arguments.

                if ((modifiers & java.lang.reflect.Modifier.STATIC) == 0)
                {
                    if (reflectedType.ContainsGenericParameters)
                    {
                        genericFlags |= flgContainsGenericParameters;
                    }

                    else if (reflectedType.IsGenericType)
                    {
                        genericFlags |= flgCombineGenericArguments;
                    }
                }
            }
        }