private IEnumerable<AssetIdentifier> DiscoverAssets(IAssetResolver assetResolver, IEnumerable<Assembly> assemblies) { TraceSources.GeneratorSource.TraceEvent(TraceEventType.Start, 0, "Discovering assets"); HashSet<AssetIdentifier> distinctSet = new HashSet<AssetIdentifier>(); IFilterContext filterContext = new FilterContext(this._cache, this._container, assetResolver, FilterState.Discovery); // find and filter all types from all assemblies foreach (Assembly asm in assemblies) { foreach (Type t in asm.GetTypes()) { // check if type survives filtering AssetIdentifier typeAsset = AssetIdentifier.FromMemberInfo(t); if (this.IsFiltered(filterContext, typeAsset)) continue; /* type was not filtered */ TraceSources.GeneratorSource.TraceEvent(TraceEventType.Information, 0, "{0}", typeAsset.AssetId); // generate namespace hierarchy if (!string.IsNullOrEmpty(t.Namespace)) { Version nsVersion = t.Module.Assembly.GetName().Version; string[] fragments = t.Namespace.Split('.'); for (int i = fragments.Length; i > 0; i--) { string ns = string.Join(".", fragments, 0, i); AssetIdentifier nsAsset = AssetIdentifier.FromNamespace(ns, nsVersion); if (distinctSet.Add(nsAsset)) yield return nsAsset; } } if (distinctSet.Add(typeAsset)) yield return typeAsset; MemberInfo[] members = t.GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MemberInfo member in members) { AssetIdentifier memberAsset = AssetIdentifier.FromMemberInfo(member); if (this.IsFiltered(filterContext, memberAsset)) continue; TraceSources.GeneratorSource.TraceEvent(TraceEventType.Information, 0, "{0}", memberAsset.AssetId); if (distinctSet.Add(memberAsset)) yield return memberAsset; } } yield return AssetIdentifier.FromAssembly(asm); } TraceSources.GeneratorSource.TraceEvent(TraceEventType.Stop, 0, "Discovering assets"); }
public bool IsFiltered(AssetIdentifier assetId) { IFilterContext filterContext = new FilterContext(this.Cache, this.Container, this.AssetResolver, FilterState.Generating); for (int i = 0; i < this._filters.Length; i++) { if (this._filters[i].Filter(filterContext, assetId)) { TraceSources.GeneratorSource.TraceEvent(TraceEventType.Verbose, 0, "{0} - Filtered by {1}", assetId.AssetId, this._filters[i]); return true; } } return false; }
public XDocument Generate(string path) { TraceSources.GeneratorSource.TraceEvent(TraceEventType.Verbose, 0, "Enrichers:"); for (int i = 0; i < this.Enrichers.Count; i++) { IEnricher enricher = this.Enrichers[i]; TraceSources.GeneratorSource.TraceEvent(TraceEventType.Verbose, 0, "[{0}] {1}", i, enricher.GetType().FullName); } TraceSources.GeneratorSource.TraceEvent(TraceEventType.Verbose, 0, "Filters:"); for (int i = 0; i < this.AssetFilters.Count; i++) { TraceSources.GeneratorSource.TraceEvent(TraceEventType.Verbose, 0, "[{0}] {1}", i, this.AssetFilters[i].GetType().FullName); } XDocument ret = new XDocument(); IAssemblyLoader assemblyLoader = new ReflectionOnlyAssemblyLoader( this._cache, this._assemblyPaths.Select(Path.GetDirectoryName)); Assembly assembly = assemblyLoader.LoadFrom(path); Asset assemblyAsset = ReflectionServices.GetAsset(assembly); XNamespace defaultNs = string.Empty; // pass in assemblyLoader instead IAssetExplorer assetExplorer = new ReflectionExplorer(assemblyLoader); IFilterContext filterContext = new FilterContext(this._cache, this._container, FilterState.Discovery, this._filters.ToArray()); // collect phase zero assets var assets = this.DiscoverAssets(assemblyAsset, assetExplorer, filterContext); // initiate output document creation ret.Add(new XElement(defaultNs + "bundle")); IProcessingContext pctx = new ProcessingContext(this._cache, this._container, this._filters, assemblyLoader, ret.Root, null, -1, assetExplorer); foreach (IEnricher enricher in this._enrichers) enricher.RegisterNamespace(pctx); // asset related classes HashSet<Asset> emittedAssets = new HashSet<Asset>(); TraceSources.GeneratorSource.TraceEvent(TraceEventType.Start, 0, "Generating document"); int phase = 0; HashSet<Asset> referencedAssets = new HashSet<Asset>(); long lastProgressOutput = Stopwatch.GetTimestamp(); // main output loop while (assets.Count > 0) { int phaseAssetCount = 0; using (TraceSources.GeneratorSource.TraceActivity("Phase {0} ({1:N0} assets)", phase, assets.Count)) { foreach (Asset asset in assets) { // skip already emitted assets if (!emittedAssets.Add(asset)) continue; phaseAssetCount++; if (((Stopwatch.GetTimestamp() - lastProgressOutput) / (double)Stopwatch.Frequency) > 5.0) { TraceSources.GeneratorSource.TraceEvent(TraceEventType.Information, 0, "Phase {0} progress {1:P1} ({2:N0}/{3:N0})", phase, phaseAssetCount / (double)assets.Count, phaseAssetCount, assets.Count); lastProgressOutput = Stopwatch.GetTimestamp(); } TraceSources.GeneratorSource.TraceEvent(TraceEventType.Verbose, 0, "Generating {0}", asset); // get hierarchy LinkedList<Asset> hierarchy = new LinkedList<Asset>(); foreach (Asset hierarchyAsset in assetExplorer.GetAssetHierarchy(asset)) hierarchy.AddFirst(hierarchyAsset); if (hierarchy.First != null) { this.BuildHierarchy(ret.Root, hierarchy.First, referencedAssets, emittedAssets, phase, assetExplorer); } } ++phase; assets.Clear(); referencedAssets.ExceptWith(emittedAssets); assets = referencedAssets.ToList(); referencedAssets.Clear(); } } TraceSources.GeneratorSource.TraceEvent(TraceEventType.Stop, 0, "Generating document"); return ret; }