コード例 #1
0
        private BlobHandle MakeSignatureHandle(MethodSignature signature)
        {
            BlobHandle handle;

            if (!_methodSignatureHandles.TryGetValue(signature, out handle))
            {
                BlobBuilder metadataSignature = new BlobBuilder();

                MethodSignatureEncoder methodSigEncoder = new BlobEncoder(metadataSignature).MethodSignature(
                    SignatureCallingConvention.Default, signature.GenericParameterCount, !signature.IsStatic);

                ReturnTypeEncoder returnTypeEncoder;
                ParametersEncoder parametersEncoder;
                methodSigEncoder.Parameters(signature.Length, out returnTypeEncoder, out parametersEncoder);

                // Return Type Sig
                EncodeTypeSignature(returnTypeEncoder.Type(), signature.ReturnType);

                // Parameter Types Sig
                for (int i = 0; i < signature.Length; i++)
                {
                    EncodeTypeSignature(parametersEncoder.AddParameter().Type(), signature[i]);
                }

                _methodSignatureHandles[signature] = handle = _metadataBuilder.GetOrAddBlob(metadataSignature);
            }

            return(handle);
        }
コード例 #2
0
        public BlobHandle GetMethodOrConstructorSignature(MethodBase methodBase)
        {
            // Method or Constructor? (must be one or the other)
            System.Diagnostics.Debug.Assert(methodBase is MethodInfo || methodBase is ConstructorInfo);

            if (methodBase.DeclaringType.IsConstructedGenericType)
            {
                // When calling methods on constructed generic types, the type is the constructed
                // type name, but the method info is the method from the open type definition. eg:
                //
                // callvirt instance void class System.Action`1<int32>::Invoke(!0)
                //                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^          ^
                //                            constructed type here             |
                //                                                              |
                //                    non constructed parameter type here ------+
                //
                // ie: NOT this:
                //
                // callvirt instance void class System.Action`1<int32>::Invoke(int32)
                //                                                             ^^^^^
                //                                                             wrong
                //
                // There doesn't seem to be a reflection API method to get the definition method.
                // Note: MethodInfo.GetGenericMethodDefinition won't work here because this is a
                // non-generic method in a generic type (as opposed to a generic method)
                //
                // Luckily both the original and the constructed type's method have the same meta
                // data token so we just go to the original generic definition and find the
                // method with the same token.
                //
                // TODO: What about generic method definitions in a generic type???
                System.Diagnostics.Debug.Assert(!methodBase.IsGenericMethod);

                var definition = methodBase.DeclaringType.GetGenericTypeDefinition();
                if (methodBase is MethodInfo)
                {
                    methodBase = definition.GetMethods(AllMethods).Single(x => x.MetadataToken == methodBase.MetadataToken);
                }
                else
                {
                    methodBase = definition.GetConstructors(AllMethods).Single(x => x.MetadataToken == methodBase.MetadataToken);
                }
            }

            // Get parameters
            var parameters = methodBase.GetParameters();

            // Create method signature encoder
            var enc = new BlobEncoder(new BlobBuilder())
                      .MethodSignature(
                MetadataHelper.ConvertCallingConvention(methodBase.CallingConvention),
                genericParameterCount: (methodBase is MethodInfo) ? ((MethodInfo)methodBase).GetGenericArguments().Length : 0,
                isInstanceMethod: !methodBase.IsStatic);

            // Add return type and parameters
            enc.Parameters(
                parameters.Length,
                (retEnc) =>
            {
                if (methodBase is MethodInfo)
                {
                    retEnc.FromSystemType(((MethodInfo)methodBase).ReturnType, this);
                }
                else
                {
                    retEnc.Void();
                }
            },
                (parEnc) =>
            {
                foreach (var par in parameters)
                {
                    if (par.ParameterType.IsByRef)
                    {
                        parEnc.AddParameter().Type(true).FromSystemType(par.ParameterType.GetElementType(), this);
                    }
                    else
                    {
                        parEnc.AddParameter().Type(false).FromSystemType(par.ParameterType, this);
                    }
                }
            }
                );

            // Get blob
            return(GetOrAddBlob(enc.Builder));
        }