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); }
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)); }