예제 #1
0
            private static ISet <TypeReference> CheckRecursion(ISubstitutionMap substitutionMap)
            {
                var substitutes = new HashSet <TypeReference>(substitutionMap.Values.Select(t => t.TargetType));

                substitutionMap.CheckRecursions(substitutes);
                return(substitutes);
            }
예제 #2
0
            private void SubstituteMethod([NotNull] MethodDefinition methodDef, [NotNull] ISubstitutionMap substitutionMap)
            {
                var methodSubstitutionMap = methodDef.CreateSubstitutionMap(_defaultParameters, substitutionMap);

                if (!ReferenceEquals(substitutionMap, methodSubstitutionMap))
                {
                    CheckRecursion(methodSubstitutionMap);
                }

                foreach (var genericParameter in methodDef.GenericParameters)
                {
                    SubstituteSignature(genericParameter.Constraints, methodSubstitutionMap);
                }

                methodDef.ReturnType = SubstituteSignature(methodDef.ReturnType, methodSubstitutionMap);

                if (methodDef.HasBody)
                {
                    if (methodDef.Body.HasVariables)
                    {
                        foreach (var variable in methodDef.Body.Variables)
                        {
                            variable.VariableType = Substitute(variable.VariableType, methodSubstitutionMap);
                        }
                    }

                    foreach (var instr in methodDef.Body.Instructions)
                    {
                        if (instr.Operand != null)
                        {
                            switch (instr.Operand)
                            {
                            case TypeReference typeRef:
                                instr.Operand = Substitute(typeRef, methodSubstitutionMap);
                                break;

                            case MethodReference methodRef:
                            {
                                if (TrySubstitute(methodRef.DeclaringType, methodSubstitutionMap, out var substituted))
                                {
                                    instr.Operand = Find(substituted.ResolveStrict(), methodRef.Resolve());
                                }
                                break;
                            }

                            case FieldReference fieldRef:
                            {
                                if (TrySubstitute(fieldRef.DeclaringType, methodSubstitutionMap, out var substituted))
                                {
                                    instr.Operand = Find(substituted.ResolveStrict(), fieldRef.Resolve());
                                }
                            }
                            break;
                            }
                        }
                    }
                }
            }
예제 #3
0
            private void SubstituteField([NotNull] FieldDefinition fieldDef, [NotNull] ISubstitutionMap substitutionMap)
            {
                var fieldSubstitutionMap = fieldDef.CreateSubstitutionMap(_defaultParameters, substitutionMap);

                if (!ReferenceEquals(substitutionMap, fieldSubstitutionMap))
                {
                    CheckRecursion(fieldSubstitutionMap);
                }

                fieldDef.FieldType = SubstituteSignature(fieldDef.FieldType, fieldSubstitutionMap);
            }
예제 #4
0
            private bool TrySubstitute([NotNull] TypeReference typeRef, [NotNull] ISubstitutionMap substitutionMap, [NotNull] Func <SubstitutionTarget, bool> doSubstitution, out TypeReference substituted)
            {
                if (substitutionMap.TryGetValue(typeRef, out var substitute))
                {
                    // ReSharper disable once AssignNullToNotNullAttribute
                    if (doSubstitution.Invoke(substitute))
                    {
                        substituted = _moduleDefinition.ImportReference(substitute.TargetType);
                        return(true);
                    }
                }

                if (typeRef is GenericInstanceType genericType)
                {
                    // ReSharper disable once AssignNullToNotNullAttribute
                    for (var i = 0; i < genericType.GenericArguments.Count; i++)
                    {
                        if (TrySubstitute(genericType.GenericArguments[i], substitutionMap, doSubstitution, out var substitutedGeneric))
                        {
                            genericType.GenericArguments[i] = substitutedGeneric;
                        }
                    }
                }

                // ReSharper disable once PossibleNullReferenceException
                foreach (var genericParameter in typeRef.GenericParameters)
                {
                    SubstituteSignature(genericParameter, substitutionMap);
                }

                if (_validatedTypes.Add(typeRef))
                {
                    if (_unmappedTypeErrors.TryGetValue(typeRef, out var error))
                    {
                        throw error;
                    }

                    var substitutedBaseType = typeRef.GetBaseTypes().FirstOrDefault(baseType => _substitutionMap.ContainsKey(baseType));

                    if (substitutedBaseType != null)
                    {
                        throw new WeavingException($"{typeRef} is not substituted, but is derived from the substituted type {substitutedBaseType}. You must substitute {typeRef}, too.", typeRef);
                    }
                }

                substituted = null;
                return(false);
            }
예제 #5
0
            private void SubstituteType([NotNull] TypeDefinition typeDef, [NotNull] ISubstitutionMap substitutionMap)
            {
                var typeSubstitution = typeDef.CreateSubstitutionMap(_defaultParameters, substitutionMap);
                var substitutes      = CheckRecursion(typeSubstitution);

                // avoid recursions...
                if (typeSubstitution.ContainsKey(typeDef) || substitutes.Contains(typeDef))
                {
                    return;
                }

                if (typeDef.HasGenericParameters)
                {
                    foreach (var genericParameter in typeDef.GenericParameters)
                    {
                        SubstituteSignature(genericParameter.Constraints, typeSubstitution);
                    }
                }

                if (typeDef.HasFields)
                {
                    foreach (var field in typeDef.Fields)
                    {
                        SubstituteField(field, typeSubstitution);
                    }
                }

                var propertyMethods = new HashSet <MethodDefinition>();

                if (typeDef.HasProperties)
                {
                    foreach (var property in typeDef.Properties)
                    {
                        SubstituteProperty(property, typeSubstitution);
                        if (property.GetMethod != null)
                        {
                            propertyMethods.Add(property.GetMethod);
                        }
                        if (property.SetMethod != null)
                        {
                            propertyMethods.Add(property.SetMethod);
                        }
                        if (property.HasOtherMethods)
                        {
                            propertyMethods.UnionWith(property.OtherMethods);
                        }
                    }
                }

                if (typeDef.HasMethods)
                {
                    foreach (var method in typeDef.Methods.Where(m => !propertyMethods.Contains(m)))
                    {
                        SubstituteMethod(method, typeSubstitution);
                    }
                }

                if (typeDef.HasNestedTypes)
                {
                    foreach (var nestedType in typeDef.NestedTypes)
                    {
                        SubstituteType(nestedType, typeSubstitution);
                    }
                }
            }
예제 #6
0
 private bool TrySubstitute([NotNull] TypeReference typeRef, [NotNull] ISubstitutionMap substitutionMap, out TypeReference substituted) =>
 TrySubstitute(typeRef, substitutionMap, subst => true, out substituted);
예제 #7
0
 private TypeReference Substitute([NotNull] TypeReference typeRef, [NotNull] ISubstitutionMap substitutionMap) =>
 TrySubstitute(typeRef, substitutionMap, out var substituted) ? substituted : typeRef;
예제 #8
0
 private bool TrySubstituteSignature([NotNull] TypeReference typeRef, [NotNull] ISubstitutionMap substitutionMap, out TypeReference substituted) =>
 TrySubstitute(typeRef, substitutionMap, subst => !subst.Parameters.DoNotChangeSignature, out substituted);
예제 #9
0
 private void SubstituteSignature([NotNull, ItemNotNull] IList <TypeReference> typeRefs, [NotNull] ISubstitutionMap substitutionMap)
 {
     for (var i = 0; i < typeRefs.Count; i++)
     {
         if (TrySubstituteSignature(typeRefs[i], substitutionMap, out var substituted))
         {
             typeRefs[i] = substituted;
         }
     }
 }
예제 #10
0
            private void SubstituteProperty([NotNull] PropertyDefinition propertyDef, [NotNull] ISubstitutionMap substitutionMap)
            {
                var propertySubstitutionMap = propertyDef.CreateSubstitutionMap(_defaultParameters, substitutionMap);

                if (!ReferenceEquals(substitutionMap, propertySubstitutionMap))
                {
                    CheckRecursion(propertySubstitutionMap);
                }

                propertyDef.PropertyType = SubstituteSignature(propertyDef.PropertyType, propertySubstitutionMap);

                if (propertyDef.GetMethod != null)
                {
                    SubstituteMethod(propertyDef.GetMethod, propertySubstitutionMap);
                }
                if (propertyDef.SetMethod != null)
                {
                    SubstituteMethod(propertyDef.SetMethod, propertySubstitutionMap);
                }
                if (propertyDef.HasOtherMethods)
                {
                    foreach (var otherMethod in propertyDef.OtherMethods)
                    {
                        SubstituteMethod(otherMethod, propertySubstitutionMap);
                    }
                }
            }