protected override void ProcessAssembly(AssemblyDefinition assemblyDef)
        {
            if (_frameworkProfile == null) {
                _frameworkProfile = assemblyDef.GuessAssemblyProfile();
            }
            if (_frameworkProfile != null) {
                _assemblyResolver.AddSearchDirectory(_frameworkProfile.ReferencesDirectory);
            }
            var typesDependenciesCollector = new CollectTypesDependenciesProcessor(_frameworkProfile);
            typesDependenciesCollector.Process(assemblyDef);

            var goodAssemblyNames = assemblyDef.Modules.SelectMany(asmDef => asmDef.AssemblyReferences);
            if(_removeNonRetargetable) {
                goodAssemblyNames = goodAssemblyNames.Where(asmRef => asmRef.IsRetargetable);
            }
            if (_frameworkProfile != null) {
                goodAssemblyNames = goodAssemblyNames.Concat(_frameworkProfile.GetFrameworkAssemblies());
            }

            var goodModules = new HashSet<ModuleDefinition>(CecilEqualityComparer.Default);
            goodModules.AddRange(assemblyDef.Modules);
            goodModules.AddRange(goodAssemblyNames.Select(_assemblyResolver.TryResolve).Where(asmDef => asmDef != null).SelectMany(asmDef => asmDef.Modules));

            var allTypesDependencies = typesDependenciesCollector.AllTypesDependencies;
            var typeDependenciesToRemove = new Queue<TypeReferenceAndDependencies>(allTypesDependencies.Where(
                kv => {
                    var typeRef = kv.Key;
                    var typeDef = typeRef.TryResolve();
                    return typeDef == null || !goodModules.Contains(typeDef.Module);
                }).Select(kv => (TypeReferenceAndDependencies)kv));

            var removedDependencies = new HashSet<TypeDependency>();
            while (typeDependenciesToRemove.Any()) {
                var typeDependencies = typeDependenciesToRemove.Dequeue();
                var typeRef = typeDependencies.Type;
                var dependencies = typeDependencies.DependingMembers;
                Trace.WriteLine(string.Format("Removing dependencies on type {0}:", typeRef), "RemoveExternalTypesUsage");
                Trace.Indent();
                foreach (var dependency in dependencies) {
                    if (!removedDependencies.Contains(dependency)) {
                        dependency.Break();
                        removedDependencies.Add(dependency);

                        var baseClassDependency = dependency as BaseClassDependency;
                        if (baseClassDependency != null) {
                            var removedClass = baseClassDependency.DerivedClass;
                            if (allTypesDependencies.ContainsKey(removedClass)) {
                                var removedClassDependencies = allTypesDependencies[removedClass];
                                typeDependenciesToRemove.Enqueue(new TypeReferenceAndDependencies(removedClass, removedClassDependencies));
                            }
                        }
                    }
                }
                Trace.Unindent();
            }

            base.ProcessAssembly(assemblyDef);
        }
        protected override void ProcessAssembly(AssemblyDefinition assemblyDef)
        {
            if (_frameworkProfile == null) {
                _frameworkProfile = assemblyDef.GuessAssemblyProfile();
            }
            if (_frameworkProfile != null) {
                foreach (var moduleDef in assemblyDef.Modules) {
                    var resolver = moduleDef.AssemblyResolver as DefaultAssemblyResolver;
                    if (resolver != null) {
                        resolver.AddSearchDirectory(_frameworkProfile.ReferencesDirectory);
                    }
                }
            }

            _usedTypeReferences = new Dictionary<TypeReference, HashSet<TypeDependency>>(CecilEqualityComparer.Default);
            base.ProcessAssembly(assemblyDef);
            var unprocessedTypes = new Queue<TypeReferenceAndDependencies>(_usedTypeReferences.Select(kv => (TypeReferenceAndDependencies)kv));
            _usedTypeReferences = null;

            var processedTypes = new Dictionary<TypeDefinition, HashSet<TypeDependency>>(CecilEqualityComparer.Default);
            var unresolvedTypes = new Dictionary<TypeReference, HashSet<TypeDependency>>(CecilEqualityComparer.Default);

            while (unprocessedTypes.Any()) {
                var typeDependencies = unprocessedTypes.Dequeue();
                var typeRef = typeDependencies.Type;
                var dependentMembers = typeDependencies.DependingMembers;

                if (typeRef == null) {
                    continue;
                }

                if (typeRef.IsGenericParameter) {
                    continue;
                }

                var typeSpec = typeRef as TypeSpecification;
                if (typeSpec != null) {
                    var elementType = typeSpec.ElementType;
                    Debug.Assert(elementType != null);
                    unprocessedTypes.Enqueue(new TypeReferenceAndDependencies(elementType, dependentMembers));

                    var genericInstanceTypeRef = typeRef as GenericInstanceType;
                    if (genericInstanceTypeRef != null) {
                        foreach (var genericArgument in genericInstanceTypeRef.GenericArguments) {
                            unprocessedTypes.Enqueue(new TypeReferenceAndDependencies(genericArgument, dependentMembers));
                        }
                    }

                    var requiredModifierTypeRef = typeRef as RequiredModifierType;
                    if (requiredModifierTypeRef != null) {
                        unprocessedTypes.Enqueue(new TypeReferenceAndDependencies(requiredModifierTypeRef.ModifierType, dependentMembers));
                    }

                    var optionalModifierTypeRef = typeRef as OptionalModifierType;
                    if (optionalModifierTypeRef != null) {
                        unprocessedTypes.Enqueue(new TypeReferenceAndDependencies(optionalModifierTypeRef.ModifierType, dependentMembers));
                    }

                    var functionPointerTypeRef = typeRef as FunctionPointerType;
                    if (functionPointerTypeRef != null) {
                        unprocessedTypes.Enqueue(new TypeReferenceAndDependencies(functionPointerTypeRef.ReturnType, dependentMembers));
                        foreach (var parameter in functionPointerTypeRef.Parameters) {
                            unprocessedTypes.Equals(parameter.ParameterType);
                            foreach (var customAttr in parameter.CustomAttributes) {
                                unprocessedTypes.Enqueue(new TypeReferenceAndDependencies(customAttr.AttributeType, dependentMembers));
                            }
                        }
                        foreach (var customAttr in functionPointerTypeRef.MethodReturnType.CustomAttributes) {
                            unprocessedTypes.Enqueue(new TypeReferenceAndDependencies(customAttr.AttributeType, dependentMembers));
                        }
                    }
                    continue;
                }

                var typeDef = typeRef as TypeDefinition;
                if (typeDef == null) {
                    typeDef = typeRef.TryResolve();
                    if (typeDef != null) {
                        unprocessedTypes.Enqueue(new TypeReferenceAndDependencies(typeDef, dependentMembers));
                    } else {
                        AddDependencies(unresolvedTypes, typeDependencies);
                        Trace.WriteLine(string.Format("Warning: Couldn't resolve type {0}", typeRef.FullName), "CollectTypesDependencies");
                    }
                    continue;
                }

                AddDependencies(processedTypes, new TypeDefinitionAndDependencies(typeDef, dependentMembers));
            }
            _resolvedTypesDependencies = processedTypes;
            _unresolvedTypesDependencies = unresolvedTypes;

            _allTypesDependencies = new Dictionary<TypeReference, HashSet<TypeDependency>>(_unresolvedTypesDependencies, CecilEqualityComparer.Default);
            foreach (var resolvedTypeDependencies in _resolvedTypesDependencies) {
                _allTypesDependencies.Add(resolvedTypeDependencies.Key, resolvedTypeDependencies.Value);
            }
        }
        protected override void ProcessAssembly(AssemblyDefinition assemblyDef)
        {
            if (_frameworkProfile == null) {
                _frameworkProfile = assemblyDef.GuessAssemblyProfile();
            }
            if (_frameworkProfile != null) {
                foreach (var moduleDef in assemblyDef.Modules) {
                    var resolver = moduleDef.AssemblyResolver as DefaultAssemblyResolver;
                    if (resolver != null) {
                        resolver.AddSearchDirectory(_frameworkProfile.ReferencesDirectory);
                    }
                }
            }

            _usedTypeReferences = new HashSet<TypeReference>(CecilEqualityComparer.Default);
            base.ProcessAssembly(assemblyDef);
            var unprocessedTypes = new Queue<TypeReference>(_usedTypeReferences);
            _usedTypeReferences = null;

            var processedTypes = new HashSet<TypeDefinition>(CecilEqualityComparer.Default);
            var unresolvedTypes = new HashSet<TypeReference>(CecilEqualityComparer.Default);

            while (unprocessedTypes.Any()) {
                var typeRef = unprocessedTypes.Dequeue();

                if (typeRef == null) {
                    continue;
                }

                if (typeRef.IsGenericParameter) {
                    continue;
                }

                var typeSpec = typeRef as TypeSpecification;
                if (typeSpec != null) {
                    var elementType = typeSpec.ElementType;
                    Debug.Assert(elementType != null);
                    unprocessedTypes.Enqueue(elementType);

                    var genericInstanceTypeRef = typeRef as GenericInstanceType;
                    if (genericInstanceTypeRef != null) {
                        foreach (var genericArgument in genericInstanceTypeRef.GenericArguments) {
                            unprocessedTypes.Enqueue(genericArgument);
                        }
                    }

                    var requiredModifierTypeRef = typeRef as RequiredModifierType;
                    if (requiredModifierTypeRef != null) {
                        unprocessedTypes.Enqueue(requiredModifierTypeRef.ModifierType);
                    }

                    var optionalModifierTypeRef = typeRef as OptionalModifierType;
                    if (optionalModifierTypeRef != null) {
                        unprocessedTypes.Enqueue(optionalModifierTypeRef.ModifierType);
                    }

                    var functionPointerTypeRef = typeRef as FunctionPointerType;
                    if (functionPointerTypeRef != null) {
                        unprocessedTypes.Enqueue(functionPointerTypeRef.ReturnType);
                        foreach (var parameter in functionPointerTypeRef.Parameters) {
                            unprocessedTypes.Equals(parameter.ParameterType);
                            foreach (var customAttr in parameter.CustomAttributes) {
                                unprocessedTypes.Enqueue(customAttr.AttributeType);
                            }
                        }
                        foreach (var customAttr in functionPointerTypeRef.MethodReturnType.CustomAttributes) {
                            unprocessedTypes.Enqueue(customAttr.AttributeType);
                        }
                    }
                    continue;
                }

                var typeDef = typeRef as TypeDefinition;
                if (typeDef == null) {
                    typeDef = typeRef.TryResolve();
                    if (typeDef != null) {
                        unprocessedTypes.Enqueue(typeDef);
                    } else {
                        unresolvedTypes.Add(typeRef);
                        Debug.WriteLine(string.Format("Cannot resolve type {0}", typeRef.FullName));
                    }
                    continue;
                }

                processedTypes.Add(typeDef);
            }
            _resolvedTypes = processedTypes;
            _unresolvedTypes = unresolvedTypes;

            _allTypes = new HashSet<TypeReference>(_unresolvedTypes.Concat(_resolvedTypes), CecilEqualityComparer.Default);
        }