protected override List <MethodDefinition> GetFilteredInjecteeMethods(
                AssemblyDefinitionCachedData assemblyDefinitionCachedData,
                List <IgnoredMemberReference> ignoredMemberReferences
                )
            {
                List <MethodDefinition> filteredInjecteeMethods =
                    base.GetFilteredInjecteeMethods(assemblyDefinitionCachedData, ignoredMemberReferences);

                filteredInjecteeMethods =
                    filteredInjecteeMethods
                    .Where(method => _injecteeMethodNames.Contains(method.GetFullSimpleName()))
                    .ToList();

                return(filteredInjecteeMethods);
            }
        private Dictionary <AssemblyDefinition, List <ResolvedInjectedMethod> > GetInjectedMethods()
        {
            var injectedAssemblyToMethodsMap = new Dictionary <AssemblyDefinition, List <ResolvedInjectedMethod> >();

            foreach (InjectedMethod sourceInjectedMethod in _injectionConfiguration.InjectedMethods)
            {
                AssemblyDefinitionCachedData assemblyDefinitionCachedData =
                    GetAssemblyDefinitionCachedData(sourceInjectedMethod.AssemblyPath, _compoundAssemblyResolver);
                MethodDefinition[] matchingMethodDefinitions =
                    assemblyDefinitionCachedData
                    .AllMethods
                    .Where(methodDefinition => methodDefinition.GetFullSimpleName() == sourceInjectedMethod.MethodFullName)
                    .ToArray();

                if (matchingMethodDefinitions.Length == 0)
                {
                    throw new MethodInlineInjectorException($"No matching methods found for {sourceInjectedMethod.MethodFullName}");
                }

                if (matchingMethodDefinitions.Length > 2)
                {
                    throw new MethodInlineInjectorException($"More than 1 matching method found for {sourceInjectedMethod.MethodFullName}");
                }

                if (!injectedAssemblyToMethodsMap.TryGetValue(
                        assemblyDefinitionCachedData.AssemblyDefinition,
                        out List <ResolvedInjectedMethod> methodDefinitions
                        ))
                {
                    methodDefinitions = new List <ResolvedInjectedMethod>();
                    injectedAssemblyToMethodsMap.Add(assemblyDefinitionCachedData.AssemblyDefinition, methodDefinitions);
                }

                MethodDefinition matchedMethodDefinition = matchingMethodDefinitions[0];
                ValidateInjectedMethod(matchedMethodDefinition);

                methodDefinitions.Add(
                    new ResolvedInjectedMethod(
                        matchedMethodDefinition,
                        sourceInjectedMethod.InjectionPosition
                        )
                    );
            }

            return(injectedAssemblyToMethodsMap);
        }
        private AssemblyDefinitionCachedData GetAssemblyDefinitionCachedData(
            string assemblyPath,
            BaseAssemblyResolver assemblyResolver)
        {
            assemblyPath = Path.GetFullPath(assemblyPath);
            if (!_assemblyPathToAssemblyMap.TryGetValue(assemblyPath, out AssemblyDefinitionCachedData assemblyDefinitionData))
            {
                Log.DebugFormat("Loading assembly at path '{0}'", assemblyPath);

                AssemblyDefinition assemblyDefinition = LoadAssemblyDefinition(assemblyPath, assemblyResolver);
                assemblyDefinitionData = new AssemblyDefinitionCachedData(assemblyDefinition);
                Log.DebugFormat(
                    "Loaded assembly at path '{0}': {1} types, {2} methods",
                    assemblyPath,
                    assemblyDefinitionData.AllTypes.Count,
                    assemblyDefinitionData.AllMethods.Count
                    );
                _assemblyPathToAssemblyMap.Add(assemblyPath, assemblyDefinitionData);
            }

            return(assemblyDefinitionData);
        }
        protected virtual List <MethodDefinition> GetFilteredInjecteeMethods(
            AssemblyDefinitionCachedData assemblyDefinitionCachedData,
            List <IgnoredMemberReference> ignoredMemberReferences)
        {
            Dictionary <string, Regex> regexCache = new Dictionary <string, Regex>();

            Log.DebugFormat("Number of types before filtering: {0}", assemblyDefinitionCachedData.AllTypes.Count);
            TypeDefinition[] types =
                assemblyDefinitionCachedData
                .AllTypes
                .Where(TestType)
                .ToArray();
            Log.DebugFormat("Number of types after filtering: {0}", types.Length);

            List <MethodDefinition> injecteeMethods =
                types
                .SelectMany(GetTestedMethodsFromType)
                .Where(ValidateInjecteeMethod)
                .ToList();

            Log.DebugFormat("Number of methods after filtering: {0}", injecteeMethods.Count);

            return(injecteeMethods);

            Regex GetFilterRegex(IgnoredMemberReference ignoredMemberReference)
            {
                if (!regexCache.TryGetValue(ignoredMemberReference.Filter, out Regex filterRegex))
                {
                    filterRegex = new Regex(ignoredMemberReference.Filter, RegexOptions.Compiled);
                    regexCache[ignoredMemberReference.Filter] = filterRegex;
                }

                return(filterRegex);
            }

            bool TestString(IgnoredMemberReference ignoredMemberReference, string fullName)
            {
                if (ignoredMemberReference.IsRegex)
                {
                    if (GetFilterRegex(ignoredMemberReference).IsMatch(fullName))
                    {
                        return(false);
                    }
                }
                else
                {
                    if (fullName.Contains(ignoredMemberReference.Filter))
                    {
                        return(false);
                    }
                }

                return(true);
            }

            bool TestType(TypeDefinition type)
            {
                foreach (IgnoredMemberReference ignoredMemberReference in ignoredMemberReferences)
                {
                    if (!ignoredMemberReference.FilterFlags.HasFlag(IgnoredMemberReferenceFlags.SkipTypes))
                    {
                        continue;
                    }

                    if (!TestTypeIgnored(type, ignoredMemberReference))
                    {
                        return(false);
                    }
                }

                return(true);
            }

            bool TestTypeIgnored(TypeDefinition type, IgnoredMemberReference ignoredMemberReference)
            {
                while (true)
                {
                    if (!TestString(ignoredMemberReference, type.FullName))
                    {
                        Log.DebugFormat("Ignored type '{0}'", type.FullName);
                        return(false);
                    }

                    if (!ignoredMemberReference.MatchAncestors || type.BaseType == null)
                    {
                        break;
                    }

                    type = type.BaseType.GetDefinition();
                }
                return(true);
            }

            IEnumerable <MethodDefinition> GetTestedMethodsFromType(TypeDefinition type)
            {
                HashSet <MethodDefinition> ignoredMethods = new HashSet <MethodDefinition>();

                foreach (PropertyDefinition property in type.Properties)
                {
                    foreach (IgnoredMemberReference ignoredMemberReference in ignoredMemberReferences)
                    {
                        if (!ignoredMemberReference.FilterFlags.HasFlag(IgnoredMemberReferenceFlags.SkipProperties))
                        {
                            continue;
                        }

                        if (ProcessPropertyIgnored(property, ignoredMemberReference, ignoredMethods))
                        {
                            break;
                        }
                    }
                }

                foreach (MethodDefinition method in type.Methods)
                {
                    foreach (IgnoredMemberReference ignoredMemberReference in ignoredMemberReferences)
                    {
                        if (!ignoredMemberReference.FilterFlags.HasFlag(IgnoredMemberReferenceFlags.SkipMethods))
                        {
                            continue;
                        }

                        if (ProcessMethodIgnored(method, ignoredMemberReference, ignoredMethods))
                        {
                            break;
                        }
                    }
                }

                return(type.Methods.Except(ignoredMethods).Distinct());
            }

            bool ProcessPropertyIgnored(PropertyDefinition property, IgnoredMemberReference ignoredMemberReference, HashSet <MethodDefinition> ignoredMethods)
            {
                PropertyDefinition startProperty = property;

                while (true)
                {
                    if (!TestString(ignoredMemberReference, property.GetFullSimpleName()))
                    {
                        Log.DebugFormat("Ignored property '{0}'", startProperty.GetFullSimpleName());
                        if (startProperty.GetMethod != null)
                        {
                            ignoredMethods.Add(startProperty.GetMethod);
                        }
                        if (startProperty.SetMethod != null)
                        {
                            ignoredMethods.Add(startProperty.SetMethod);
                        }
                        return(false);
                    }

                    if (!ignoredMemberReference.MatchAncestors)
                    {
                        break;
                    }

                    PropertyDefinition baseProperty = property.GetBaseProperty();
                    if (baseProperty == property)
                    {
                        break;
                    }

                    property = baseProperty;
                }

                return(true);
            }

            bool ProcessMethodIgnored(MethodDefinition method, IgnoredMemberReference ignoredMemberReference, HashSet <MethodDefinition> ignoredMethods)
            {
                MethodDefinition startMethod = method;

                while (true)
                {
                    if (!TestString(ignoredMemberReference, method.GetFullSimpleName()))
                    {
                        ignoredMethods.Add(startMethod);
                        Log.DebugFormat("Ignored method '{0}'", startMethod.GetFullSimpleName());
                        return(false);
                    }

                    if (!ignoredMemberReference.MatchAncestors)
                    {
                        break;
                    }

                    MethodDefinition baseMethod = method.GetBaseMethod();
                    if (baseMethod == method)
                    {
                        break;
                    }

                    method = baseMethod;
                }

                return(true);
            }
        }
        private ResolvedInjecteeAssembly GetInjecteeAssembly(InjecteeAssembly sourceInjecteeAssembly)
        {
            List <IgnoredMemberReference>   ignoredMemberReferences   = new List <IgnoredMemberReference>();
            List <AllowedAssemblyReference> allowedAssemblyReferences = new List <AllowedAssemblyReference>();

            void LoadIgnoredMemberReferences(IEnumerable <IIgnoredMemberReference> items)
            {
                foreach (IIgnoredMemberReference item in items)
                {
                    if (item is IgnoredMemberReference ignoredMemberReference)
                    {
                        ignoredMemberReferences.Add(ignoredMemberReference);
                        continue;
                    }

                    if (item is IgnoredMemberReferenceInclude ignoredMemberReferenceInclude)
                    {
                        try {
                            Log.DebugFormat("Loading ignored member references list include at '{0}'", ignoredMemberReferenceInclude.Path);
                            string includeXml = File.ReadAllText(ignoredMemberReferenceInclude.Path);
                            IgnoredMemberReferencesIncludeLoader ignoredMemberReferencesIncludeLoader =
                                SimpleXmlSerializationUtility.XmlDeserializeFromString <IgnoredMemberReferencesIncludeLoader>(includeXml);
                            LoadIgnoredMemberReferences(ignoredMemberReferencesIncludeLoader.Items);
                        } catch (Exception e) {
                            Console.WriteLine(e);
                            throw new MethodInlineInjectorException(
                                      $"Unable to load ignored member references list include at '{ignoredMemberReferenceInclude.Path}'",
                                      e
                                      );
                        }
                    }
                }
            }

            void LoadAllowedAssemblyReferences(IEnumerable <IAllowedAssemblyReference> items)
            {
                foreach (IAllowedAssemblyReference item in items)
                {
                    if (item is AllowedAssemblyReference allowedAssemblyReference)
                    {
                        allowedAssemblyReferences.Add(allowedAssemblyReference);
                        continue;
                    }

                    if (item is AllowedAssemblyReferenceInclude allowedAssemblyReferenceInclude)
                    {
                        Log.DebugFormat("Loading allowed assembly references list include at '{0}'", allowedAssemblyReferenceInclude.Path);
                        try {
                            string includeXml = File.ReadAllText(allowedAssemblyReferenceInclude.Path);
                            AllowedAssemblyReferenceIncludeLoader allowedAssemblyReferencesLoader =
                                SimpleXmlSerializationUtility.XmlDeserializeFromString <AllowedAssemblyReferenceIncludeLoader>(includeXml);
                            LoadAllowedAssemblyReferences(allowedAssemblyReferencesLoader.Items);
                        } catch (Exception e) {
                            throw new MethodInlineInjectorException(
                                      $"Unable to load allowed assembly references list include at '{allowedAssemblyReferenceInclude.Path}'",
                                      e
                                      );
                        }
                    }
                }
            }

            LoadIgnoredMemberReferences(sourceInjecteeAssembly.IgnoredMemberReferences);
            LoadAllowedAssemblyReferences(sourceInjecteeAssembly.AllowedAssemblyReferences);

            List <ResolvedAllowedAssemblyReference> resolvedAllowedAssemblyReferences =
                allowedAssemblyReferences
                .Select(item => new ResolvedAllowedAssemblyReference(AssemblyNameReference.Parse(item.Name), item.Path, item.StrictNameCheck))
                .ToList();

            // Configure assembly resolver for this assembly
            IgnoringExceptionsAssemblyResolver assemblyResolver             = CreateAssemblyResolver(resolvedAllowedAssemblyReferences);
            AssemblyDefinitionCachedData       assemblyDefinitionCachedData =
                GetAssemblyDefinitionCachedData(sourceInjecteeAssembly.AssemblyPath, assemblyResolver);

            Log.DebugFormat(
                "Calculating injectee methods in assembly '{0}'",
                assemblyDefinitionCachedData.AssemblyDefinition.MainModule.FullyQualifiedName);

            List <MethodDefinition> filteredInjecteeMethods =
                GetFilteredInjecteeMethods(assemblyDefinitionCachedData, ignoredMemberReferences);

            ResolvedInjecteeAssembly resolvedInjecteeAssembly =
                new ResolvedInjecteeAssembly(
                    assemblyDefinitionCachedData.AssemblyDefinition,
                    filteredInjecteeMethods,
                    resolvedAllowedAssemblyReferences,
                    assemblyResolver
                    );

            return(resolvedInjecteeAssembly);
        }