//public AddinEngine() : this(AddinOptions.Create()) { } public AddinEngine(AddinOptions addinOptions) { _addinRelationManager = new AddinRelationManager(); _addinFramework = new AddinFramework(addinOptions); _assemblyResolver = new RuntimeAssemblyResolver(_addinFramework); _runtimeExtensionLoader = new RuntimeExtensionLoader(_assemblyResolver, _addinFramework.ExtensionPointFactory, _addinFramework.ExtensionBuilderFactory); }
protected AddinResolver(AddinStorage addinStorage, AddinRelationManager addinRelationManager, ConvertionManager convertionManager) { AddinStorage = addinStorage; AddinRelationManager = addinRelationManager; ConvertionManager = convertionManager; _addinParsers = new List <AddinParser> { new XmlAddinParser() }; }
// @return value: whether the persistence file has been updated. public ResolutionResult Resolve(INameConvention nameConvention, AddinFileSettings fileSettings, AssemblyLoadPolicy assemblyLoadPolicy, AddinStorage addinStorage, AddinRelationManager relationManager, ScanFilePackResult scanFilePackResult) { var ctx = new ResolutionContext(); var cm = new ConvertionManager(); InitializeDataTransformers(ctx, cm); if (assemblyLoadPolicy.PrivateAssemblyProbingDirectories != null) { foreach (var privateAssemblyProbingDirectory in assemblyLoadPolicy.PrivateAssemblyProbingDirectories) { AssemblyResolution.AddSearchDirectory(privateAssemblyProbingDirectory); } } var resolver = new DefaultAddinResolver(addinStorage, relationManager, cm); // 强制 ExtensionBuilder 节点应用 NameConvention return(resolver.Resolve(nameConvention, ctx, scanFilePackResult)); }
// this method should split the existing addins into the following kind: // 1. updated addins // 2. unaffected addins // 3. directly affected addins // 4. indirectly affected addins // then, decide how to register assets of these addins and whether they need resolution, according to each kind. // and finally, return the addin list that need to be resolved. protected List <AddinResolution> RegisterExistingAssets(ResolutionResult resolutionResult, ResolutionContext ctx, AddinCollision addinCollision) { // ================================================= // 1. 首先确定 AddinStorage 中各个现有 addin 的状态:未受影响的、已更新的、间接受影响的 // check whether there are updated addins. // and if there are any, mark their operation status as updated. List <AddinRecord> updatedAddins = null; for (int i = AddinStorage.AddinRecordCount - 1; i >= 0; i--) { var existingAddin = AddinStorage.Get(i); var addinId = existingAddin.AddinId; AddinResolution adnResolution; // 如果 ResolutionContext 中已存在相同 guid 的插件,则表明这是一个更新的插件 if (!ctx.TryGetAddin(addinId, out adnResolution)) { continue; } AddinStorage.Remove(existingAddin); //AddinRelationManager.RemoveRelationMap(existingAddin); //adnResolution.OperationStatus = AddinOperationStatus.Updated; updatedAddins = updatedAddins ?? new List <AddinRecord>(); updatedAddins.Add(existingAddin); } if (AddinStorage.AddinRecordCount == 0) { return(null); // all addins are updated addins. } // mark directly affected and indirectly affected addins. List <AddinRecord> directlyAffectedAddins = null, indirectlyAffectedAddins = null; if (updatedAddins != null) { directlyAffectedAddins = AddinRelationManager.TryGetAffectingAddins(updatedAddins); if (directlyAffectedAddins != null) { indirectlyAffectedAddins = AddinRelationManager.TryGetAllAffectingAddins(directlyAffectedAddins); //if (indirectlyAffectedAddins != null) //{ // for (int i = indirectlyAffectedAddins.Count - 1; i >= 0; i--) // { // if (directlyAffectedAddins.Contains(indirectlyAffectedAddins[i])) // indirectlyAffectedAddins.RemoveAt(i); // } //} } } // ================================================= // 2. 根据 AddinStorage 中各个现有 addin 的状态,将它们注册到 ResolutionContext if (updatedAddins != null) { foreach (var updatedAddin in updatedAddins) { var ebs = updatedAddin.GetAllExtensionBuilders(); if (ebs != null) { foreach (var eb in ebs) { if (eb.ExtensionBuilderKind == ExtensionBuilderKind.Declared) { // 将已更新插件的 ExtensionBuilderPath 映射注册到 context。 // 因为在解析 Extension 时,是根据 ExtensionBuilderPath 查找 ExtensionBuilder 的,但对于 [directlyAffectedAddins 插件的 Extension] 来说,它们并不 // 保存自身依赖的 updateAddins 的 ExtensionBuilder 的 ExtensionBuilderPath。 // 所以,只能在解析前先将 updateAddins 的 ExtensionBuilder 的 ExtensionBuilderPath 注册到 context,后面解析 [directlyAffectedAddins 插件的 Extension] // 时,才能通过 uid 获得目标 ExtensionBuilder 的 path,继而找到 ExtensionBuilder ctx.RegisterExtensionBuilderPath(eb.Uid, eb.GetPath()); } } } } } List <AddinResolution> resolableAddins = null; // decide how to register assets of these addins and whether to resolve these addins according to their operation status. if (directlyAffectedAddins != null) { foreach (var directlyAffectedAddin in directlyAffectedAddins) { AddinStorage.Remove(directlyAffectedAddin); var resolvableAddin = DoRegisterExistingAddin(resolutionResult, ctx, addinCollision, directlyAffectedAddin, AddinOperationStatus.DirectlyAffected); resolableAddins = resolableAddins ?? new AddinResolutionSet(); resolableAddins.Add(resolvableAddin); } } if (indirectlyAffectedAddins != null) { foreach (var indirectlyAffectedAddin in indirectlyAffectedAddins) { AddinStorage.Remove(indirectlyAffectedAddin); var resolvableAddin = DoRegisterExistingAddin(resolutionResult, ctx, addinCollision, indirectlyAffectedAddin, AddinOperationStatus.IndirectlyAffected); resolableAddins = resolableAddins ?? new AddinResolutionSet(); resolableAddins.Add(resolvableAddin); } } // since the updated, directly affected and indirectly affected, they are all removed, so the rest is unaffected for (int i = AddinStorage.AddinRecordCount - 1; i >= 0; i--) { var unaffectedAddin = AddinStorage.Get(i); AddinStorage.Remove(unaffectedAddin); var resolvableAddin = DoRegisterExistingAddin(resolutionResult, ctx, addinCollision, unaffectedAddin, AddinOperationStatus.Unaffected); resolableAddins = resolableAddins ?? new AddinResolutionSet(); resolableAddins.Add(resolvableAddin); } return(resolableAddins); }
internal DefaultAddinResolver(AddinStorage addinStorage, AddinRelationManager addinRelationManager, ConvertionManager convertionManager) : base(addinStorage, addinRelationManager, convertionManager) { }