public List <TExtensionInstance> InvokeMatchingFactories <TExtensionInstance, TExtensionFactory, TMetadataView> (IEnumerable <Lazy <TExtensionFactory, TMetadataView> > lazyFactories, Func <TExtensionFactory, TExtensionInstance> getter, IContentType dataContentType, object errorSource) where TMetadataView : IContentTypeMetadata // content type is required where TExtensionFactory : class where TExtensionInstance : class { var result = new List <TExtensionInstance>(); foreach (var lazyFactory in lazyFactories) { if (ExtensionSelector.ContentTypeMatch(dataContentType, lazyFactory.Metadata.ContentTypes)) { try { TExtensionFactory factory = lazyFactory.Value; if (factory != null) { TExtensionInstance instance = getter(factory); if (instance != null) { result.Add(instance); } } } catch (Exception e) { HandleException(errorSource, e); } } } return(result); }
/// <summary> /// Given a list of extensions that provide text view roles and content types, filter the list and return that /// subset which matches the content types and at least one of the roles in the provided set of roles. /// </summary> public static List <Lazy <TProvider, TMetadataView> > SelectMatchingExtensions <TProvider, TMetadataView> (IEnumerable <Lazy <TProvider, TMetadataView> > providerHandles, IContentType documentContentType, IContentType excludedContentType, ITextViewRoleSet viewRoles) where TMetadataView : IContentTypeAndTextViewRoleMetadata // both content type and text view role are required { var result = new List <Lazy <TProvider, TMetadataView> >(); foreach (var providerHandle in providerHandles) { // first, check content type match if ((excludedContentType == null || !ExtensionSelector.ContentTypeMatch(excludedContentType, providerHandle.Metadata.ContentTypes)) && ExtensionSelector.ContentTypeMatch(documentContentType, providerHandle.Metadata.ContentTypes) && viewRoles.ContainsAny(providerHandle.Metadata.TextViewRoles)) { result.Add(providerHandle); } } return(result); }
// The algorithm here is that assets can have a Name attribute and one or more Replaces attribute. // Assets without names are treated normally (they are always considered eligible). // Named assets are considered ineligible if: // There is a "better" asset with the same name (better means a more specific content type). // There is another assert with a Replaces attribute that matches the name of the asset. public IEnumerable <Lazy <TExtensionFactory, TMetadataView> > FindEligibleFactories <TExtensionFactory, TMetadataView> (IEnumerable <Lazy <TExtensionFactory, TMetadataView> > lazyFactories, IContentType dataContentType, IContentTypeRegistryService contentTypeRegistryService) where TMetadataView : INamedContentTypeMetadata // content type is required where TExtensionFactory : class { Dictionary <string, List <Lazy <TExtensionFactory, TMetadataView> > > namedFactories = null; HashSet <string> replaced = null; foreach (var lazyFactory in lazyFactories) { if (ExtensionSelector.ContentTypeMatch(dataContentType, lazyFactory.Metadata.ContentTypes)) { if (string.IsNullOrEmpty(lazyFactory.Metadata.Name)) { yield return(lazyFactory); } else { if (namedFactories == null) { namedFactories = new Dictionary <string, List <Lazy <TExtensionFactory, TMetadataView> > >(StringComparer.OrdinalIgnoreCase); } List <Lazy <TExtensionFactory, TMetadataView> > factories; if (!namedFactories.TryGetValue(lazyFactory.Metadata.Name, out factories)) { factories = new List <Lazy <TExtensionFactory, TMetadataView> >(); namedFactories.Add(lazyFactory.Metadata.Name, factories); } factories.Add(lazyFactory); if (lazyFactory.Metadata.Replaces != null) { if (replaced == null) { replaced = new HashSet <string>(StringComparer.OrdinalIgnoreCase); } foreach (var s in lazyFactory.Metadata.Replaces) { replaced.Add(s); } } } } } if (namedFactories != null) { foreach (var candidates in namedFactories.Values) { var candidate = candidates[0]; if ((replaced == null) || !replaced.Contains(candidate.Metadata.Name)) { SortCandidates(candidates, dataContentType, contentTypeRegistryService); yield return(candidates[0]); } } } }