/// <summary> /// Adds the interface layer for the given instance to the dynamic binding context. /// </summary> public static void AddInterfaceLayer(this IDynamicBindingContext context, IProductElement element) { Guard.NotNull(() => context, context); Guard.NotNull(() => element, element); //TODO: If we ever allow automation to be defined on an extension point, // then for every pattern that implments and extension point, we must add a key to the cache for that extensionPoint.DefinitionId var layer = default(object); var key = new ToolkitInterfaceLayerCacheKey(element, element.DefinitionId); if (element.Root != null && element.Root.ProductState != null && element.Root.ProductState.PropertyBag != null && !element.Root.ProductState.PropertyBag.TryGetValue(key, out layer)) { layer = GetInterfaceLayer(element); if (layer != null) { element.Root.ProductState.PropertyBag[key] = layer; } } if (layer != null) { context.AddExportsFromInterfaces(layer); } }
/// <summary> /// Attempts to retrieve (from cache or by creating and caching it the first time) /// the typed interface layer proxy defined by the runtime instance, without knowing /// its type. This is used in the add rules to initialize the interface layers. /// </summary> public static IToolkitInterface GetInterfaceLayer(this IInstanceBase instance) { Guard.NotNull(() => instance, instance); if (instance.Info == null) { return(null); } var key = new ToolkitInterfaceLayerCacheKey(instance, instance.DefinitionId); var layer = default(object); var canCache = instance.Root != null && instance.Root.ProductState != null && instance.Root.ProductState.PropertyBag != null; if (canCache && instance.Root.ProductState.PropertyBag.TryGetValue(key, out layer)) { return((IToolkitInterface)layer); } var interfaceService = default(IToolkitInterfaceService); if (!canCache || (interfaceService = instance.Root.ProductState.TryGetService <IToolkitInterfaceService>()) == null) { tracer.Warn(Resources.ToolkitInterfaceLayer_ServiceUnavailable); return(null); } var definitionId = Guid.Empty; var proxyType = interfaceService.AllInterfaces .Where(export => !string.IsNullOrEmpty(export.Metadata.DefinitionId) && Guid.TryParse(export.Metadata.DefinitionId, out definitionId)) .Where(export => export.Metadata.ExtensionId == instance.Info.GetRoot().ExtensionId&& definitionId == instance.DefinitionId) .Select(export => export.Metadata.ProxyType) .FirstOrDefault(); if (proxyType != null) { try { layer = Activator.CreateInstance(proxyType, instance); if (layer != null && canCache) { instance.Root.ProductState.PropertyBag[key] = layer; } return(layer as IToolkitInterface); } catch (System.Reflection.TargetInvocationException tie) { tracer.Error(tie.InnerException, Resources.ToolkitInterfaceLayer_TraceFailedInstantiation, proxyType); } } return(null); }
/// <summary> /// Retrieves a cached interface layer proxy or creates a new one using /// the toolkit specified and caches it the first time. /// </summary> private static TInterface GetInterfaceLayer <TInterface>(IInstanceBase element, Func <TInterface> toolkit) where TInterface : class { var typed = element as TInterface; if (typed != null) { return(typed); } // We'll never be able to cache in this case. if (element.Root == null || element.Root.ProductState == null || element.Root.ProductState.PropertyBag == null) { return(toolkit()); } var layer = default(object); var key = new ToolkitInterfaceLayerCacheKey(element, element.DefinitionId); if (element.Root.ProductState.PropertyBag.TryGetValue(key, out layer)) { return(layer as TInterface); } else { var result = toolkit(); if (result != default(TInterface)) { element.Root.ProductState.PropertyBag[key] = result; } return(result); } }