public void ResolveGenericParameter() { var gt1 = new TypeReference("namespace", "Type1", TestModule, MetadataScope); var gt2 = new TypeReference("namespace", "Type2", TestModule, MetadataScope); var gp1 = new GenericParameter("GP", gt1); var gp2 = new GenericParameter("GP", gt2); gt1.GenericParameters.Add(gp1); gt2.GenericParameters.Add(gp2); var git1 = new GenericInstanceType(gt1); git1.GenericArguments.Add(T2); var git2 = new GenericInstanceType(gt2); git2.GenericArguments.Add(T2); Assert.AreEqual(T2, MethodSignature.ResolveGenericParameter(gp1, git1)); Assert.AreEqual(T2, MethodSignature.ResolveGenericParameter(gp2, git2)); // Generic parameters with same name but different owners. Assert.AreEqual(null, MethodSignature.ResolveGenericParameter(gp2, git1)); Assert.AreEqual(null, MethodSignature.ResolveGenericParameter(gp1, git2)); }
private void CacheSignature(MethodReference method, MethodSignature signature, bool isConstructor) { Func <GenericParameter, bool> filter = (gp) => { // If the generic parameter can be expanded given the type that declared the method, don't cache locally. var resolved = MethodSignature.ResolveGenericParameter(gp, method.DeclaringType); // Note that we have to ensure the resolved type is not generic either. A generic parameter can resolve to a // *different* generic parameter, and that is still correct - i.e. SomeMethod<A> calls SomeMethod<B>, // in that case resolving B will yield A. if ((resolved != gp) && (resolved != null) && !TypeUtil.IsOpenType(resolved)) { return(false); } var ownerMethod = gp.Owner as MethodReference; if (ownerMethod == null) { return(true); } if (ownerMethod == method) { return(false); } // FIXME: Nulls? else if (ownerMethod.Resolve() == method.Resolve()) { return(false); } else { return(true); } }; var cacheLocally = false; if (TypeUtil.IsOpenType(signature.ReturnType, filter)) { cacheLocally = true; } else if (signature.ParameterTypes.Any((gp) => TypeUtil.IsOpenType(gp, filter))) { cacheLocally = true; } else if (TypeUtil.IsOpenType(method.DeclaringType, filter)) { cacheLocally = true; } var set = GetCacheSet(cacheLocally); var record = new CachedSignatureRecord(method, signature, isConstructor); if (!set.Signatures.ContainsKey(record)) { set.Signatures.Add(record, set.Signatures.Count); } }
private static TypeReference ResolveTypeReference(MethodReference method, TypeReference typeReference, Dictionary <GenericParameter, int> mappings) { var resolvedMethod = method.Resolve(); return(GenericTypesRewriter.ResolveTypeReference( typeReference, (tr, resolutionStack) => { if (tr is GenericParameter) { var gp = (GenericParameter)tr; if (resolutionStack.Count(typeInStack => TypeUtil.TypesAreEqual(typeInStack, gp)) > 1) { return GenericTypesRewriter.ReplaceWithGenericArgument(gp, mappings); } var result = MethodSignature.ResolveGenericParameter(gp, method.DeclaringType); if (result is GenericParameter) { gp = (GenericParameter)result; result = null; } if (result == null) { if (gp.Owner is MethodReference) { var mr = (MethodReference)gp.Owner; if (mr.Resolve() == resolvedMethod) { return gp; } } return GenericTypesRewriter.ReplaceWithGenericArgument(gp, mappings); } return result; } return tr; }, null)); }