标签:查找 can 自动 目录 comm 节点 delete rect list
1 <runtime> 2 ... 3 <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 4 <probing privatePath="App_Data/Dependencies" /> 5 ... 6 </assemblyBinding> 7 </runtime>
1 // For all existing extensions in the site, ask each loader if they can 2 // load that extension. 3 foreach (var extension in context.AvailableExtensions) { 4 ProcessExtension(context, extension); 5 }
它的处理过程如下:
先放上全量代码:
1 private void ProcessExtension(ExtensionLoadingContext context, ExtensionDescriptor extension) { 2 var extensionProbes = context.AvailableExtensionsProbes.ContainsKey(extension.Id) ? 3 context.AvailableExtensionsProbes[extension.Id] : 4 Enumerable.Empty<ExtensionProbeEntry>(); 5 // materializes the list 6 extensionProbes = extensionProbes.ToArray(); 7 8 if (Logger.IsEnabled(LogLevel.Debug)) { 9 Logger.Debug("Loaders for extension \"{0}\": ", extension.Id); 10 foreach (var probe in extensionProbes) { 11 Logger.Debug(" Loader: {0}", probe.Loader.Name); 12 Logger.Debug(" VirtualPath: {0}", probe.VirtualPath); 13 Logger.Debug(" VirtualPathDependencies: {0}", string.Join(", ", probe.VirtualPathDependencies)); 14 } 15 } 16 17 var moduleReferences = 18 context.AvailableExtensions 19 .Where(e => 20 context.ReferencesByModule.ContainsKey(extension.Id) && 21 context.ReferencesByModule[extension.Id].Any(r => StringComparer.OrdinalIgnoreCase.Equals(e.Id, r.Name))) 22 .ToList(); 23 24 var processedModuleReferences = 25 moduleReferences 26 .Where(e => context.ProcessedExtensions.ContainsKey(e.Id)) 27 .Select(e => context.ProcessedExtensions[e.Id]) 28 .ToList(); 29 30 var activatedExtension = extensionProbes.FirstOrDefault( 31 e => e.Loader.IsCompatibleWithModuleReferences(extension, processedModuleReferences) 32 ); 33 34 var previousDependency = context.PreviousDependencies.FirstOrDefault( 35 d => StringComparer.OrdinalIgnoreCase.Equals(d.Name, extension.Id) 36 ); 37 38 if (activatedExtension == null) { 39 Logger.Warning("No loader found for extension \"{0}\"!", extension.Id); 40 } 41 42 var references = ProcessExtensionReferences(context, activatedExtension); 43 44 foreach (var loader in _loaders) { 45 if (activatedExtension != null && activatedExtension.Loader.Name == loader.Name) { 46 Logger.Information("Activating extension \"{0}\" with loader \"{1}\"", activatedExtension.Descriptor.Id, loader.Name); 47 loader.ExtensionActivated(context, extension); 48 } 49 else if (previousDependency != null && previousDependency.LoaderName == loader.Name) { 50 Logger.Information("Deactivating extension \"{0}\" from loader \"{1}\"", previousDependency.Name, loader.Name); 51 loader.ExtensionDeactivated(context, extension); 52 } 53 } 54 55 if (activatedExtension != null) { 56 context.NewDependencies.Add(new DependencyDescriptor { 57 Name = extension.Id, 58 LoaderName = activatedExtension.Loader.Name, 59 VirtualPath = activatedExtension.VirtualPath, 60 References = references 61 }); 62 } 63 64 // Keep track of which loader we use for every extension 65 // This will be needed for processing references from other dependent extensions 66 context.ProcessedExtensions.Add(extension.Id, activatedExtension); 67 }
1 var extensionProbes = context.AvailableExtensionsProbes.ContainsKey(extension.Id) ? 2 context.AvailableExtensionsProbes[extension.Id] : 3 Enumerable.Empty<ExtensionProbeEntry>(); 4 5 // materializes the list 6 extensionProbes = extensionProbes.ToArray();
一般来说只有~\Modules和自定义的拓展模块目录下的拓展模块会存在多个探测信息,因为它们被预编译加载器和动态编译加载器同时探测到(bin目录和csproj文件)。
1 var moduleReferences = 2 context.AvailableExtensions 3 .Where(e => 4 context.ReferencesByModule.ContainsKey(extension.Id) && 5 context.ReferencesByModule[extension.Id].Any(r => StringComparer.OrdinalIgnoreCase.Equals(e.Id, r.Name))) 6 .ToList(); 7 8 var processedModuleReferences = 9 moduleReferences 10 .Where(e => context.ProcessedExtensions.ContainsKey(e.Id)) 11 .Select(e => context.ProcessedExtensions[e.Id]) 12 .ToList();
1 var activatedExtension = extensionProbes.FirstOrDefault( 2 e => e.Loader.IsCompatibleWithModuleReferences(extension, processedModuleReferences) 3 );
1 var previousDependency = context.PreviousDependencies.FirstOrDefault( 2 d => StringComparer.OrdinalIgnoreCase.Equals(d.Name, extension.Id) 3 );
处理引用:
1 var referenceNames = (context.ReferencesByModule.ContainsKey(activatedExtension.Descriptor.Id) ? 2 context.ReferencesByModule[activatedExtension.Descriptor.Id] : 3 Enumerable.Empty<ExtensionReferenceProbeEntry>()) 4 .Select(r => r.Name) 5 .Distinct(StringComparer.OrdinalIgnoreCase);
1 public override void ReferenceActivated(ExtensionLoadingContext context, ExtensionReferenceProbeEntry referenceEntry) { 2 if (string.IsNullOrEmpty(referenceEntry.VirtualPath)) 3 return; 4 5 string sourceFileName = _virtualPathProvider.MapPath(referenceEntry.VirtualPath); 6 7 // Copy the assembly if it doesn‘t exist or if it is older than the source file. 8 bool copyAssembly = 9 !_assemblyProbingFolder.AssemblyExists(referenceEntry.Name) || 10 File.GetLastWriteTimeUtc(sourceFileName) > _assemblyProbingFolder.GetAssemblyDateTimeUtc(referenceEntry.Name); 11 12 if (copyAssembly) { 13 context.CopyActions.Add(() => _assemblyProbingFolder.StoreAssembly(referenceEntry.Name, sourceFileName)); 14 15 // We need to restart the appDomain if the assembly is loaded 16 if (_hostEnvironment.IsAssemblyLoaded(referenceEntry.Name)) { 17 Logger.Information("ReferenceActivated: Reference \"{0}\" is activated with newer file and its assembly is loaded, forcing AppDomain restart", referenceEntry.Name); 18 context.RestartAppDomain = true; 19 } 20 } 21 }
1 foreach (var loader in _loaders) { 2 if (activatedExtension != null && activatedExtension.Loader.Name == loader.Name) { 3 Logger.Information("Activating extension \"{0}\" with loader \"{1}\"", activatedExtension.Descriptor.Id, loader.Name); 4 loader.ExtensionActivated(context, extension); 5 } 6 else if (previousDependency != null && previousDependency.LoaderName == loader.Name) { 7 Logger.Information("Deactivating extension \"{0}\" from loader \"{1}\"", previousDependency.Name, loader.Name); 8 loader.ExtensionDeactivated(context, extension); 9 } 10 } 11 12 if (activatedExtension != null) { 13 context.NewDependencies.Add(new DependencyDescriptor { 14 Name = extension.Id, 15 LoaderName = activatedExtension.Loader.Name, 16 VirtualPath = activatedExtension.VirtualPath, 17 References = references 18 }); 19 } 20 21 // Keep track of which loader we use for every extension 22 // This will be needed for processing references from other dependent extensions 23 context.ProcessedExtensions.Add(extension.Id, activatedExtension);
1 public override void ExtensionActivated(ExtensionLoadingContext ctx, ExtensionDescriptor extension) { 2 if (_reloadWorkaround.AppDomainRestartNeeded) { 3 Logger.Information("ExtensionActivated: Module \"{0}\" has changed, forcing AppDomain restart", extension.Id); 4 ctx.RestartAppDomain = _reloadWorkaround.AppDomainRestartNeeded; 5 } 6 }
1 public override void ExtensionDeactivated(ExtensionLoadingContext ctx, ExtensionDescriptor extension) { 2 if (_assemblyProbingFolder.AssemblyExists(extension.Id)) { 3 ctx.DeleteActions.Add( 4 () => { 5 Logger.Information("ExtensionDeactivated: Deleting assembly \"{0}\" from probing directory", extension.Id); 6 _assemblyProbingFolder.DeleteAssembly(extension.Id); 7 }); 8 9 // We need to restart the appDomain if the assembly is loaded 10 if (_hostEnvironment.IsAssemblyLoaded(extension.Id)) { 11 Logger.Information("ExtensionDeactivated: Module \"{0}\" is deactivated and its assembly is loaded, forcing AppDomain restart", extension.Id); 12 ctx.RestartAppDomain = true; 13 } 14 } 15 }
引用:
1 private void DeleteAssembly(ExtensionLoadingContext ctx, string moduleName) { 2 var assemblyPath = _virtualPathProvider.Combine("~/bin", moduleName + ".dll"); 3 if (_virtualPathProvider.FileExists(assemblyPath)) { 4 ctx.DeleteActions.Add( 5 () => { 6 Logger.Information("ExtensionRemoved: Deleting assembly \"{0}\" from bin directory (AppDomain will restart)", moduleName); 7 File.Delete(_virtualPathProvider.MapPath(assemblyPath)); 8 }); 9 ctx.RestartAppDomain = true; 10 } 11 }
1 private void ProcessContextCommands(ExtensionLoadingContext ctx) { 2 Logger.Information("Executing list of operations needed for loading extensions..."); 3 foreach (var action in ctx.DeleteActions) { 4 action(); 5 } 6 7 foreach (var action in ctx.CopyActions) { 8 action(); 9 } 10 }
1 // And finally save the new entries in the dependencies folder 2 _dependenciesFolder.StoreDescriptors(context.NewDependencies); 3 _extensionDependenciesManager.StoreDependencies(context.NewDependencies, desc => GetExtensionHash(context, desc));
标签:查找 can 自动 目录 comm 节点 delete rect list
原文地址:http://www.cnblogs.com/selimsong/p/6085229.html