예제 #1
0
        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));
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
            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));
            }