private PointcutSelector CreateAdviceSelector(ReflectionNode node, WeavingContext context) { var adviceSelector = new PointcutSelector(); var excludeAdviceAttributes = node.CustomAttributes.Where(ca => ca.AttributeType.SafeEquivalent(context.ExcludeAdviceAttributeType)); foreach (var excludeAdviceAttribute in excludeAdviceAttributes) { var rule = new PointcutSelectorRule(); // full names wildcards if (excludeAdviceAttribute.ConstructorArguments.Count == 1) { rule.Names.AddRange(GetStrings(excludeAdviceAttribute.ConstructorArguments[0].Value)); } // then named properties foreach (var namedArgument in excludeAdviceAttribute.NamedArguments) { // names (which should usually not happen) if (namedArgument.Name == nameof(ExcludeAdvicesAttribute.AdvicesTypes)) { rule.Names.AddRange(GetStrings(namedArgument.Value)); } } adviceSelector.ExcludeRules.Add(rule); } if (node.Parent != null) { adviceSelector = GetAdviceSelector(node.Parent, context) + adviceSelector; } return(adviceSelector); }
/// <summary> /// Creates the marker definition. /// </summary> /// <param name="typeDefinition">The type definition.</param> /// <param name="context">The context.</param> /// <returns></returns> private MarkerDefinition CreateMarkerDefinition(TypeDef typeDefinition, WeavingContext context) { var priorityAttributes = typeDefinition.CustomAttributes.Where(a => a.AttributeType.SafeEquivalent(context.PriorityAttributeType)).ToList(); if (priorityAttributes.Count > 1) { Logging.WriteWarning("Advice {0} has more than one priority. Using the first found", typeDefinition.FullName); } #if uneedednow int priority = 0; if (priorityAttributes.Count > 0) { var priorityAttribute = priorityAttributes[0]; priority = (int)priorityAttribute.ConstructorArguments[0].Value; Logging.WriteDebug("Advice {0} has priority {1}", typeDefinition.FullName, priority); } #endif var abstractTarget = typeDefinition.CustomAttributes.Any(a => a.AttributeType.SafeEquivalent(context.AbstractTargetAttributeType)); if (abstractTarget) { Logging.WriteDebug("Advice {0} abstracts target", typeDefinition.FullName); } var markerDefinition = new MarkerDefinition(typeDefinition, abstractTarget); return(markerDefinition); }
/// <summary> /// Weaves method with weaving advices <see cref="IWeavingAdvice"/>. /// </summary> /// <param name="markedMethod">The marked method.</param> /// <param name="context">The context.</param> private void RunWeavingAdvices(MarkedNode markedMethod, WeavingContext context) { var method = markedMethod.Node.Method; var methodName = method.Name; // our special recipe, with weaving advices var weavingAdvicesMarkers = GetAllMarkers(markedMethod.Node, context.WeavingAdviceInterfaceType, context).Select(t => t.Item2).ToArray(); var typeDefinition = markedMethod.Node.Method.DeclaringType; var initialType = TypeLoader.GetType(typeDefinition); var weaverMethodWeavingContext = new WeaverMethodWeavingContext(typeDefinition, initialType, methodName, context, TypeResolver, Logging); foreach (var weavingAdviceMarker in weavingAdvicesMarkers) { Logging.WriteDebug("Weaving method '{0}' using weaving advice '{1}'", method.FullName, weavingAdviceMarker.Type.FullName); var weavingAdviceType = TypeLoader.GetType(weavingAdviceMarker.Type); var weavingAdvice = (IWeavingAdvice)Activator.CreateInstance(weavingAdviceType); if (weavingAdvice is IMethodWeavingAdvice methodWeavingAdvice && !method.IsGetter && !method.IsSetter) { methodWeavingAdvice.Advise(weaverMethodWeavingContext); } } if (weaverMethodWeavingContext.TargetMethodName != methodName) { method.Name = weaverMethodWeavingContext.TargetMethodName; } }
/// <summary> /// Initializes a new instance of the <see cref="WeaverMethodWeavingContext" /> class. /// </summary> /// <param name="typeDefinition">The type definition (type being built).</param> /// <param name="type">The type (original type).</param> /// <param name="targetMethodName">Name of the target method.</param> /// <param name="context">The context.</param> /// <param name="typeResolver">The type resolver.</param> /// <param name="logging">The logging.</param> public WeaverMethodWeavingContext(TypeDef typeDefinition, Type type, string targetMethodName, WeavingContext context, TypeResolver typeResolver, ILogging logging) : base(type, targetMethodName) { _typeDefinition = typeDefinition; _context = context; _typeResolver = typeResolver; _logging = logging; }
private static IEnumerable <FieldDef> GetRemovableFields(MethodDef method, WeavingContext context) { return(from instruction in method.Body.Instructions let fieldReference = instruction.Operand as IField where fieldReference is not null && fieldReference.DeclaringType.SafeEquivalent(method.DeclaringType) let fieldDefinition = fieldReference.ResolveFieldDef() where fieldDefinition.CustomAttributes.Any(a => a.AttributeType.SafeEquivalent(context.CompilerGeneratedAttributeType)) select fieldDefinition); }
private PointcutSelector GetAdviceSelector(ReflectionNode node, WeavingContext context) { if (node.AdviceSelector != null) { return(node.AdviceSelector); } return(node.AdviceSelector = CreateAdviceSelector(node, context)); }
/// <summary> /// Gets the rules at given advice. /// </summary> /// <param name="adviceType">Type of the advice.</param> /// <param name="context">The context.</param> /// <returns></returns> private PointcutSelector GetPointcutSelector(TypeDef adviceType, WeavingContext context) { if (context.AdvicesRules.TryGetValue(adviceType, out var pointcutRules)) { return(pointcutRules); } context.AdvicesRules[adviceType] = pointcutRules = CreatePointcutSelector(adviceType, context); return(pointcutRules); }
/// <summary> /// Determines whether the <see cref="MarkedNode"/> is included by pointcut /// </summary> /// <param name="markedNode">The marked node.</param> /// <param name="context">The context.</param> /// <returns> /// <c>true</c> if [is included by pointcut] [the specified marked node]; otherwise, <c>false</c>. /// </returns> private bool IsIncludedByPointcut(MarkedNode markedNode, WeavingContext context) { var isIncludedByPointcut = GetPointcutSelectors(markedNode, context).Any(s => s.Select(markedNode.Node.Method)); if (!isIncludedByPointcut) { Logging.WriteDebug("Excluding method '{0}' according to pointcut rules", markedNode.Node.Method.FullName); } return(isIncludedByPointcut); }
/// <summary> /// Creates the pointcut rules for a given advice. /// </summary> /// <param name="adviceTypeDef">The advice type definition.</param> /// <param name="context">The context.</param> /// <returns></returns> private PointcutSelector CreatePointcutSelector(TypeDef adviceTypeDef, WeavingContext context) { var pointcutSelector = new PointcutSelector(); foreach (var customAttribute in adviceTypeDef.CustomAttributes) { pointcutSelector += CreatePointcutSelector(customAttribute, context); } return(pointcutSelector); }
/// <summary> /// Gets the rules at given <see cref="MarkedNode"/>. /// </summary> /// <param name="markedNode">The marked node.</param> /// <param name="context">The context.</param> /// <returns></returns> private PointcutSelector GetPointcutSelector(MarkedNode markedNode, WeavingContext context) { var rules = PointcutSelector.EmptySelector; foreach (var markerDefinition in markedNode.Definitions) { rules += GetPointcutSelector(markerDefinition.Type, context); } return(rules); }
/// <summary> /// Creates the pointcut rules for a given advice. /// </summary> /// <param name="adviceType">Type of the advice.</param> /// <param name="context">The context.</param> /// <returns></returns> private PointcutSelector CreatePointcutSelector(ITypeDefOrRef adviceType, WeavingContext context) { var adviceTypeDef = TypeResolver.Resolve(adviceType); var rules = new PointcutSelector(); foreach (var customAttribute in adviceTypeDef.CustomAttributes) { rules += CreatePointcutSelector(customAttribute, context); } return(rules); }
private static void AddGeneratedAttribute(MethodDefUser innerMethod, WeavingContext context) { // does this happen? Not sure. if (context.ExecutionPointAttributeDefaultCtor == null) { return; } var generatedAttribute = new CustomAttribute(context.ExecutionPointAttributeDefaultCtor); innerMethod.CustomAttributes.Add(generatedAttribute); }
/// <summary> /// Gets the marker definition. /// </summary> /// <param name="typeDefinition">The type definition.</param> /// <param name="context">The context.</param> /// <returns></returns> private MarkerDefinition GetMarkerDefinition(TypeDef typeDefinition, WeavingContext context) { lock (_markerDefinitions) { if (_markerDefinitions.TryGetValue(typeDefinition, out var markerDefinition)) { return(markerDefinition); } markerDefinition = CreateMarkerDefinition(typeDefinition, context); _markerDefinitions[typeDefinition] = markerDefinition; return(markerDefinition); } }
/// <summary> /// Writes the invocation call. /// </summary> /// <param name="instructions">The instructions.</param> /// <param name="context">The context.</param> /// <param name="arguments">The arguments.</param> /// <exception cref="InvalidOperationException"> /// </exception> private void WriteProceedCall(Instructions instructions, WeavingContext context, params InvocationArgument[] arguments) { var proceedMethod = GetProceedMethod(arguments, instructions.Module, context); foreach (var argument in arguments) { if (argument.HasValue) { argument.Emit(instructions); } } instructions.Emit(OpCodes.Call, proceedMethod); }
/// <summary> /// Creates the pointcut rules for a given advice. /// </summary> /// <param name="adviceTypeDef">The advice type definition.</param> /// <param name="context">The context.</param> /// <returns></returns> private PointcutSelector CreatePointcutSelector(TypeDef adviceTypeDef, WeavingContext context) { var pointcutSelector = new PointcutSelector(); foreach (var customAttribute in adviceTypeDef.CustomAttributes) { pointcutSelector += CreatePointcutSelector(customAttribute, context); } var baseType = adviceTypeDef.BaseType.ResolveTypeDef(); if (baseType != null) { pointcutSelector += GetPointcutSelector(baseType, context); } return(pointcutSelector); }
private WeavingContext CreateWeavingContext(ModuleDefMD moduleDefinition) { var context = new WeavingContext { CompilerGeneratedAttributeType = moduleDefinition.Import(typeof(CompilerGeneratedAttribute)), PriorityAttributeType = TypeResolver.Resolve(moduleDefinition, typeof(PriorityAttribute)), AbstractTargetAttributeType = TypeResolver.Resolve(moduleDefinition, typeof(AbstractTargetAttribute)), AdviceInterfaceType = TypeResolver.Resolve(moduleDefinition, typeof(IAdvice)), WeavingAdviceInterfaceType = TypeResolver.Resolve(moduleDefinition, typeof(IWeavingAdvice)), ExecutionPointAttributeDefaultCtor = moduleDefinition.Import(TypeResolver.Resolve(moduleDefinition, typeof(ExecutionPointAttribute)).FindDefaultConstructor()), ExcludePointcutAttributeType = TypeResolver.Resolve(moduleDefinition, typeof(ExcludePointcutAttribute)), IncludePointcutAttributeType = TypeResolver.Resolve(moduleDefinition, typeof(IncludePointcutAttribute)), ExcludeAdviceAttributeType = TypeResolver.Resolve(moduleDefinition, typeof(ExcludeAdvicesAttribute)), }; return(context); }
private IMethod GetDefaultProceedMethod(ModuleDef module, WeavingContext context) { if (context.InvocationProceedMethod == null) { var invocationType = TypeResolver.Resolve(module, typeof(Invocation)); if (invocationType == null) { throw new InvalidOperationException(); } var proceedMethodReference = invocationType.Methods.SingleOrDefault(m => m.IsStatic && m.Name == nameof(Invocation.ProceedAdvice2)); if (proceedMethodReference == null) { throw new InvalidOperationException(); } context.InvocationProceedMethod = module.SafeImport(proceedMethodReference); } return(context.InvocationProceedMethod); }
private WeavingContext CreateWeavingContext(ModuleDef moduleDefinition) { var context = new WeavingContext { CompilerGeneratedAttributeType = moduleDefinition.Import(typeof(CompilerGeneratedAttribute)), PriorityAttributeType = TypeResolver.Resolve(moduleDefinition, typeof(PriorityAttribute)), AbstractTargetAttributeType = TypeResolver.Resolve(moduleDefinition, typeof(AbstractTargetAttribute)), AdviceInterfaceType = TypeResolver.Resolve(moduleDefinition, typeof(IAdvice)), WeavingAdviceInterfaceType = TypeResolver.Resolve(moduleDefinition, typeof(IWeavingAdvice)), ExecutionPointAttributeDefaultCtor = moduleDefinition.Import(TypeResolver.Resolve(moduleDefinition, typeof(ExecutionPointAttribute))?.FindDefaultConstructor()), ExcludePointcutAttributeType = TypeResolver.Resolve(moduleDefinition, typeof(ExcludePointcutAttribute)), IncludePointcutAttributeType = TypeResolver.Resolve(moduleDefinition, typeof(IncludePointcutAttribute)), ExcludeAdviceAttributeType = TypeResolver.Resolve(moduleDefinition, typeof(ExcludeAdvicesAttribute)), IntroducedFieldType = TypeResolver.Resolve(moduleDefinition, typeof(IntroducedField <>)), SharedIntroducedFieldType = TypeResolver.Resolve(moduleDefinition, typeof(SharedIntroducedField <>)), #pragma warning disable 618 IntroducedFieldsType = TypeResolver.Resolve(moduleDefinition, typeof(IntroducedFieldsRegistry)), #pragma warning restore 618 }; if (context.AdviceInterfaceType is not null) { if (context.ExecutionPointAttributeDefaultCtor is null) { Logging.WriteError("ExecutionPointAttribute default ctor was not found"); } if (context.ExcludePointcutAttributeType is null) { Logging.WriteError("ExcludePointcutAttributeType was not found"); } if (context.IncludePointcutAttributeType is null) { Logging.WriteError("IncludePointcutAttributeType was not found"); } if (context.ExcludeAdviceAttributeType is null) { Logging.WriteError("ExcludeAdviceAttributeType was not found"); } } return(context); }
private PointcutSelector CreateAdviceSelector(ReflectionNode node, WeavingContext context) { var adviceSelector = new PointcutSelector(); // Advices should not advise themselves var typeReflectionNode = node as TypeReflectionNode; if (typeReflectionNode != null && IsMarker(typeReflectionNode.TypeDefinition, context.AdviceInterfaceType)) { Logging.WriteDebug("Excluding {0} from itself", typeReflectionNode.TypeDefinition.FullName); adviceSelector.ExcludeRules.Add(new PointcutSelectorRule(typeReflectionNode.TypeDefinition.FullName)); } if (context.ExcludeAdviceAttributeType != null) { var excludeAdviceAttributes = node.CustomAttributes.Where(ca => ca.AttributeType.SafeEquivalent(context.ExcludeAdviceAttributeType)); foreach (var excludeAdviceAttribute in excludeAdviceAttributes) { var rule = new PointcutSelectorRule(); // full names wildcards if (excludeAdviceAttribute.ConstructorArguments.Count == 1) { rule.Names.AddRange(GetStrings(excludeAdviceAttribute.ConstructorArguments[0].Value)); } // then named properties foreach (var namedArgument in excludeAdviceAttribute.NamedArguments) { // names (which should usually not happen) if (namedArgument.Name == nameof(ExcludeAdvicesAttribute.AdvicesTypes)) { rule.Names.AddRange(GetStrings(namedArgument.Value)); } } adviceSelector.ExcludeRules.Add(rule); } } if (node.Parent != null) { adviceSelector = GetAdviceSelector(node.Parent, context) + adviceSelector; } return(adviceSelector); }
private WeavingContext CreateWeavingContext(ModuleDef moduleDefinition) { var context = new WeavingContext { CompilerGeneratedAttributeType = moduleDefinition.Import(typeof(CompilerGeneratedAttribute)), PriorityAttributeType = TypeResolver.Resolve(moduleDefinition, typeof(PriorityAttribute)), AbstractTargetAttributeType = TypeResolver.Resolve(moduleDefinition, typeof(AbstractTargetAttribute)), AdviceInterfaceType = TypeResolver.Resolve(moduleDefinition, typeof(IAdvice)), WeavingAdviceInterfaceType = TypeResolver.Resolve(moduleDefinition, typeof(IWeavingAdvice)), ExecutionPointAttributeDefaultCtor = moduleDefinition.Import(TypeResolver.Resolve(moduleDefinition, typeof(ExecutionPointAttribute))?.FindDefaultConstructor()), ExcludePointcutAttributeType = TypeResolver.Resolve(moduleDefinition, typeof(ExcludePointcutAttribute)), IncludePointcutAttributeType = TypeResolver.Resolve(moduleDefinition, typeof(IncludePointcutAttribute)), ExcludeAdviceAttributeType = TypeResolver.Resolve(moduleDefinition, typeof(ExcludeAdvicesAttribute)), }; if (context.AdviceInterfaceType != null) { if (context.ExecutionPointAttributeDefaultCtor == null) { Logging.WriteError("ExecutionPointAttribute default ctor was not found"); } if (context.ExcludePointcutAttributeType == null) { Logging.WriteError("ExcludePointcutAttributeType was not found"); } if (context.IncludePointcutAttributeType == null) { Logging.WriteError("IncludePointcutAttributeType was not found"); } if (context.ExcludeAdviceAttributeType == null) { Logging.WriteError("ExcludeAdviceAttributeType was not found"); } } return(context); }
/// <summary> /// Gets the marked methods. /// </summary> /// <param name="reflectionNode">The reflection node.</param> /// <param name="markerInterface">The marker interface.</param> /// <param name="context">The context.</param> /// <returns></returns> private IEnumerable <MarkedNode> GetMarkedMethods(ReflectionNode reflectionNode, ITypeDefOrRef markerInterface, WeavingContext context) { var ancestorsToChildren = reflectionNode.GetAncestorsToDescendants().ToArray(); return(from node in ancestorsToChildren where node.Method is not null let allMakersNode = new MarkedNode(node, GetAllMarkers(node, markerInterface, context).Select(t => t.Item2)) where allMakersNode.Definitions.Any() && IsIncludedByPointcut(allMakersNode, context) //&& !IsDeclaredByValue(node) let includedMarkersNode = new MarkedNode(node, allMakersNode.Definitions.Where(d => IsIncludedByNode(d, node, context))) where includedMarkersNode.Definitions.Any() select includedMarkersNode); }
/// <summary> /// Creates the pointcut rules from an advice attribute. /// The custom attribute provided has to be either <see cref="ExcludePointcutAttribute"/> or <see cref="IncludePointcutAttribute"/> /// If not the return <see cref="PointcutSelector"/> are empty /// </summary> /// <param name="customAttribute">The custom attribute.</param> /// <param name="context">The context.</param> /// <returns></returns> private PointcutSelector CreatePointcutSelector(CustomAttribute customAttribute, WeavingContext context) { var rules = new PointcutSelector(); rules.IncludeRules.AddRange(CreatePointcutSelectorRule(customAttribute, context.IncludePointcutAttributeType)); rules.ExcludeRules.AddRange(CreatePointcutSelectorRule(customAttribute, context.ExcludePointcutAttributeType)); return(rules); }
/// <summary> /// Gets the rules at given <see cref="MarkedNode"/>. /// </summary> /// <param name="markedNode">The marked node.</param> /// <param name="context">The context.</param> /// <returns></returns> private IEnumerable <PointcutSelector> GetPointcutSelectors(MarkedNode markedNode, WeavingContext context) { return(markedNode.Definitions.Select(d => GetPointcutSelector(d.Type, context))); }
/// <summary> /// Creates the pointcut rules from an advice attribute. /// The custom attribute provided has to be either <see cref="ExcludePointcutAttribute"/> or <see cref="IncludePointcutAttribute"/> /// If not the returned <see cref="PointcutSelector"/> is empty /// </summary> /// <param name="customAttribute">The custom attribute.</param> /// <param name="context">The context.</param> /// <returns></returns> private PointcutSelector CreatePointcutSelector(CustomAttribute customAttribute, WeavingContext context) { var pointcutSelector = new PointcutSelector(); if (context.IncludePointcutAttributeType != null) { pointcutSelector.IncludeRules.AddRange(CreatePointcutSelectorRule(customAttribute, context.IncludePointcutAttributeType)); } if (context.ExcludePointcutAttributeType != null) { pointcutSelector.ExcludeRules.AddRange(CreatePointcutSelectorRule(customAttribute, context.ExcludePointcutAttributeType)); } return(pointcutSelector); }
/// <summary> /// Introduces the member. /// </summary> /// <param name="moduleDefinition">The module definition.</param> /// <param name="memberName">Name of the member.</param> /// <param name="memberType">Type of the member.</param> /// <param name="isStatic">if set to <c>true</c> [is static].</param> /// <param name="adviceType">The advice.</param> /// <param name="advisedType">The type definition.</param> /// <param name="markerAttribute">The marker attribute ctor.</param> /// <param name="introducedMemberName">Name of the introduced member.</param> /// <param name="isNotSerialized">if set to <c>true</c> [is not serialized].</param> /// <param name="context">The context.</param> private void IntroduceMember(ModuleDef moduleDefinition, string memberName, ITypeDefOrRef memberType, bool isStatic, ITypeDefOrRef adviceType, TypeDef advisedType, ICustomAttributeType markerAttribute, string introducedMemberName, bool isNotSerialized, WeavingContext context) { if (IsIntroduction(memberType, out var introducedFieldType, out var isShared, context)) { var introducedFieldName = IntroductionRules.GetName(adviceType.Namespace, adviceType.Name, introducedMemberName, memberName, isShared); lock (advisedType.Fields) { if (advisedType.Fields.All(f => f.Name != introducedFieldName)) { var fieldAttributes = (InjectAsPrivate ? FieldAttributes.Private : FieldAttributes.Public) | (isNotSerialized ? FieldAttributes.NotSerialized : 0); if (isStatic) { fieldAttributes |= FieldAttributes.Static; } Logging.WriteDebug("Introduced field type '{0}'", introducedFieldType.FullName); var introducedFieldTypeReference = TypeImporter.Import(moduleDefinition, introducedFieldType.ToTypeSig()); var introducedField = new FieldDefUser(introducedFieldName, new FieldSig(introducedFieldTypeReference), fieldAttributes); introducedField.CustomAttributes.Add(new CustomAttribute(markerAttribute)); advisedType.Fields.Add(introducedField); } } } }
private static IEnumerable <FieldDef> GetRemovableFields(IList <MarkedNode> nodes, WeavingContext context) { var type = nodes.First().Node.Method.DeclaringType; // get all types var allRemovableFields = GetRemovableFields(type.Methods, context); // then all referenced fields that will be dereferenced var toBeRemovedFields = GetRemovableFields(nodes.Select(n => n.Node.Method), context); // and remove only where count are equals var removableFields = from t in toBeRemovedFields where allRemovableFields.Contains(t) select t.Item1; return(removableFields); }
/// <summary> /// Gets all attributes that implement the given advice interface /// </summary> /// <param name="reflectionNode">The reflection node.</param> /// <param name="markerInterface">The advice interface.</param> /// <param name="context">The context.</param> /// <returns></returns> private IEnumerable <Tuple <ReflectionNode, MarkerDefinition> > GetAllMarkers(ReflectionNode reflectionNode, ITypeDefOrRef markerInterface, WeavingContext context) { var markers = reflectionNode.GetAncestorsToDescendants() .Select(n => new { Node = n, Attributes = n.CustomAttributes }) .SelectMany(n => n.Attributes.Select(a => new { Node = n.Node, Attribute = a }) .Where(a => !a.Attribute.AttributeType.DefinitionAssembly.IsSystem()) .Select(a => new { Node = a.Node, Type = ResolveTypeOrGenericDefinition(a.Attribute.AttributeType) }) .Where(t => IsMarker(t.Type, markerInterface))) .Select(t => Tuple.Create(t.Node, GetMarkerDefinition(t.Type, context))); return(markers); }
/// <summary> /// Determines whether the specified <see cref="ReflectionNode"/> allows the given <see cref="MarkerDefinition"/>. /// </summary> /// <param name="markerDefinition">The marker definition.</param> /// <param name="node">The node.</param> /// <param name="context">The context.</param> /// <returns> /// <c>true</c> if [is included by node] [the specified node]; otherwise, <c>false</c>. /// </returns> private bool IsIncludedByNode(MarkerDefinition markerDefinition, ReflectionNode node, WeavingContext context) { var adviceSelector = GetAdviceSelector(node, context); var isIncluded = adviceSelector.Select(markerDefinition.Type); if (!isIncluded) { Logging.WriteDebug("Method '{0}' excluded advice '{1}'", node.Method.FullName, markerDefinition.Type.FullName); } return(isIncluded); }
private static IEnumerable <Tuple <FieldDef, int> > GetRemovableFields(IEnumerable <MethodDef> methods, WeavingContext context) { var allFields = methods.SelectMany(m => GetRemovableFields(m, context)); var fieldsCount = allFields.GroupBy(f => f); return(fieldsCount.Select(f => Tuple.Create(f.Key, f.Count()))); }
/// <summary> /// Determines whether the advice member is introduction, based on its type. /// </summary> /// <param name="adviceMemberTypeReference">The type reference.</param> /// <param name="introducedFieldType">Type of the introduced field.</param> /// <param name="isShared">if set to <c>true</c> the introduced field is shared among advices of the same type.</param> /// <param name="context">The context.</param> /// <returns> /// <c>true</c> if the specified advice member type reference is introduction; otherwise, <c>false</c>. /// </returns> private bool IsIntroduction(ITypeDefOrRef adviceMemberTypeReference, out ITypeDefOrRef introducedFieldType, out bool isShared, WeavingContext context) { introducedFieldType = null; isShared = false; var genericAdviceMemberTypeReference = adviceMemberTypeReference.TryGetGenericInstSig(); if (genericAdviceMemberTypeReference is null) { return(false); } var genericAdviceMemberTypeDefinition = TypeResolver.Resolve(genericAdviceMemberTypeReference.GenericType.TypeDefOrRef); if (genericAdviceMemberTypeDefinition is null) // in DEBUG or bogus cases, this may not be resolved. Whatever, this is not our field { return(false); } if (!genericAdviceMemberTypeDefinition.ImplementsType(context.IntroducedFieldType, TypeResolver)) { return(false); } introducedFieldType = genericAdviceMemberTypeReference.GenericArguments[0].ToTypeDefOrRef(); isShared = genericAdviceMemberTypeDefinition.ImplementsType(context.SharedIntroducedFieldType, TypeResolver); return(true); }