/// <summary>Handles cases where a markup extension provides a value for a property of <see cref="T:System.Windows.Setter" /> object.</summary> /// <param name="targetObject">The object where the markup extension sets the value.</param> /// <param name="eventArgs">Data that is relevant for markup extension processing.</param> // Token: 0x0600089C RID: 2204 RVA: 0x0001BFD0 File Offset: 0x0001A1D0 public static void ReceiveMarkupExtension(object targetObject, XamlSetMarkupExtensionEventArgs eventArgs) { if (targetObject == null) { throw new ArgumentNullException("targetObject"); } if (eventArgs == null) { throw new ArgumentNullException("eventArgs"); } Setter setter = targetObject as Setter; if (setter == null || eventArgs.Member.Name != "Value") { return; } MarkupExtension markupExtension = eventArgs.MarkupExtension; if (markupExtension is StaticResourceExtension) { StaticResourceExtension staticResourceExtension = markupExtension as StaticResourceExtension; setter.Value = staticResourceExtension.ProvideValueInternal(eventArgs.ServiceProvider, true); eventArgs.Handled = true; return; } if (markupExtension is DynamicResourceExtension || markupExtension is BindingBase) { setter.Value = markupExtension; eventArgs.Handled = true; } }
private static Style GetStyle(IServiceProvider service, StaticResourceExtension resource) { var style = resource.ProvideValue(service) as Style; if (style == null) { throw new InvalidOperationException( string.Format( "Could not find style with resource key {0}.", resource.ResourceKey)); } return style; }
/// <summary> /// Returns a style that merges all styles with the keys specified in the constructor. /// </summary> /// <param name="serviceProvider">The service provider for this markup extension.</param> /// <returns>A style that merges all styles with the keys specified in the constructor.</returns> public override object ProvideValue(IServiceProvider serviceProvider) { Style resultStyle = new Style(); foreach(string currentResourceKey in resourceKeys) { object key = currentResourceKey; if(currentResourceKey == ".") { IProvideValueTarget service = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget)); key = service.TargetObject.GetType(); } Style currentStyle = new StaticResourceExtension(key).ProvideValue(serviceProvider) as Style; if(currentStyle == null) throw new InvalidOperationException("Could not find style with resource key " + currentResourceKey + "."); resultStyle.Merge(currentStyle); } return resultStyle; }
/// <summary> /// Returns a style that merges all styles with the keys specified by ResourceKeys property. /// </summary> public override object ProvideValue( IServiceProvider serviceProvider ) { Contract.RequiresNotNull( ResourceKeys, "ResourceKeys" ); var resourceKeys = ResourceKeys.Split( new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries ); Contract.Requires( resourceKeys.Length > 0, "No input resource keys specified." ); var resultStyle = new Style(); foreach( var currentResourceKey in resourceKeys ) { var currentStyle = new StaticResourceExtension( currentResourceKey ).ProvideValue( serviceProvider ) as Style; Contract.Invariant( currentStyle != null, "Could not find style with resource key " + currentResourceKey + "." ); AddTo( currentStyle, resultStyle ); } return resultStyle; }
/// <summary> /// Convert the OptimizedStaticResource and StaticResource items into StaticResourceHolders. /// A StaticResourceHolder is derived from StaticResourceExtension and is a MarkupExtension. /// The differences is that it contain a DeferredResourceReference as its "PrefetchedValue". /// DeferredResourceReferences hold the dictionary and the key of the resource. It is a /// way of looking up the reference now (for later use) but not expanding the entry. /// Also the dictionary has a reference back to the Deferrred Reference. If dictionary entry /// is modifed the DeferredResourceReference is told and it will grab the old value. /// StaticResourceHolder is a MarkupExtension and thus can be returned as a "Value" in the Node Stream. /// /// Issue: If there is a ResourceDictionary inside the deferred entry, the entries inside that /// RD will not be evaluated when resolving DeferredResourceReferences for a key in that same entry. /// Thus the OptimizedStaticResource will either be erronously "not found" or may even map to some /// incorrect value higher in the parse tree. So... In StaticResourceExtension.ProvideValue() /// when we have a DeferredResourceReference we search the Deferred Content for a better /// closer value before using the DeferredReference. /// See StaticResourceExtension.FindTheResourceDictionary() for more details. /// </summary> // As a memory optimization this method is passed a staticResourceExtension instance to use as // a worker when calling TryProvideValueInternal, which saves us having to allocate on every call. private void SetOptimizedStaticResources(IList<object> staticResources, IServiceProvider serviceProvider, StaticResourceExtension staticResourceWorker) { Debug.Assert(staticResources != null && staticResources.Count > 0); for (int i = 0; i < staticResources.Count; i++) { object keyValue = null; // Process OptimizedStaticResource var optimizedStaticResource = staticResources[i] as OptimizedStaticResource; if (optimizedStaticResource != null) { keyValue = optimizedStaticResource.KeyValue; } else { // Process StaticResource (it holds the NodeList of the StaticResourceExtension) var staticResource = staticResources[i] as StaticResource; if (staticResource != null) { // find and evaluate the Key value of the SR in the SR's node stream. keyValue = GetStaticResourceKeyValue(staticResource, serviceProvider); Debug.Assert(keyValue != null, "Didn't find the ResourceKey property or x:PositionalParameters directive"); } else { Debug.Assert(false, "StaticResources[] entry is not a StaticResource not OptimizedStaticResource"); continue; // other types of entries are not processed. } } // Lookup the Key in the current context. [And return a Deferred Reference Holding SR to it] // The current context is the Key table at the top of the Compiled Dictionary. // We will look at keys above us in this dictionary and in the dictionaries in objects above // us on the parse stack. And then look in the App and System Themems. // This isn't always good enough. The Static Resource referenced inside the entry may refer // to a entry in a sub-dictionary inside the deferred entry. There is other code, later // when evaluating StaticResourceHolders, that does an search of the part that is missed here. staticResourceWorker.ResourceKey = keyValue; object obj = staticResourceWorker.TryProvideValueInternal(serviceProvider, true /*allowDeferredReference*/, true /* mustReturnDeferredResourceReference */); Debug.Assert(obj is DeferredResourceReference); staticResources[i] = new StaticResourceHolder(keyValue, obj as DeferredResourceReference); } }
private void SetKeys(IList<KeyRecord> keyCollection, IServiceProvider serviceProvider) { _numDefer = keyCollection.Count; // Allocate one StaticResourceExtension object to use as a "worker". StaticResourceExtension staticResourceWorker = new StaticResourceExtension(); // Use the array Count property to avoid range checking inside the loop for (int i = 0; i < keyCollection.Count; i++) { KeyRecord keyRecord = keyCollection[i]; if (keyRecord != null) { object value = GetKeyValue(keyRecord, serviceProvider); // Update the HasImplicitStyles flag UpdateHasImplicitStyles(value); if (keyRecord != null && keyRecord.HasStaticResources) { SetOptimizedStaticResources(keyRecord.StaticResources, serviceProvider, staticResourceWorker); } _baseDictionary.Add(value, keyRecord); if (TraceResourceDictionary.IsEnabled) { TraceResourceDictionary.TraceActivityItem( TraceResourceDictionary.SetKey, this, value); } } else { throw new ArgumentException(SR.Get(SRID.KeyCollectionHasInvalidKey)); } } // Notify owners of the HasImplicitStyles flag value // but there is not need to fire an invalidation. NotifyOwners(new ResourcesChangeInfo(null, this)); }
internal virtual object GetExtensionValue( IOptimizedMarkupExtension optimizedMarkupExtensionRecord, string propertyName) { object innerExtensionValue = null; object valueObject = null; short memberId = optimizedMarkupExtensionRecord.ValueId; short extensionTypeId = optimizedMarkupExtensionRecord.ExtensionTypeId; switch (extensionTypeId) { case (short)KnownElements.StaticExtension: valueObject = GetStaticExtensionValue(memberId); break; case (short)KnownElements.DynamicResourceExtension: innerExtensionValue = GetInnerExtensionValue(optimizedMarkupExtensionRecord); valueObject = new DynamicResourceExtension(innerExtensionValue); break; case (short)KnownElements.StaticResourceExtension: innerExtensionValue = GetInnerExtensionValue(optimizedMarkupExtensionRecord); valueObject = new StaticResourceExtension(innerExtensionValue); break; } if (valueObject == null) { string valueTypeName = string.Empty; switch (extensionTypeId) { case (short)KnownElements.StaticExtension: valueTypeName = typeof(StaticExtension).FullName; break; case (short)KnownElements.DynamicResourceExtension: valueTypeName = typeof(DynamicResourceExtension).FullName; break; case (short)KnownElements.StaticResourceExtension: valueTypeName = typeof(StaticResourceExtension).FullName; break; } ThrowException(SRID.ParserCannotConvertPropertyValue, propertyName, valueTypeName); } return valueObject; }
// The end of the constructor parameter section has been reached. Create an // instance of the object after finding the appropriate constructor and converting // all of the objects held on the stack. internal virtual void ReadConstructorParametersEndRecord() { Type elementType = ParentContext.ExpectedType; short positiveElementTypeId = (short)-ParentContext.ExpectedTypeId; object param = null; ArrayList paramList = null; int paramCount; object instance = null; bool foundInstance = false; if( TraceMarkup.IsEnabled ) { TraceMarkup.Trace( TraceEventType.Start, TraceMarkup.CreateMarkupExtension, elementType ); } if (CurrentContext.CheckFlag(ReaderFlags.SingletonConstructorParam)) { param = CurrentContext.ObjectData; paramCount = 1; // Fast code path for [static/dynamic] resource extensions & // Type/Static/TemplateBinding extensions switch (positiveElementTypeId) { case (short)KnownElements.TypeExtension: // Note that this assumes that TypeExtension has a // constructor with one param of type Type or String. Type t = param as Type; if (t != null) { instance = new TypeExtension(t); } else { Debug.Assert(param is String); instance = new TypeExtension((String)param); } foundInstance = true; break; case (short)KnownElements.StaticResourceExtension: // Note that this assumes that StaticResourceExtension has a // constructor with one param of type object. instance = new StaticResourceExtension(param); foundInstance = true; break; case (short)KnownElements.DynamicResourceExtension: // Note that this assumes that DynamicResourceExtension has a // constructor with one param of type object. instance = new DynamicResourceExtension(param); foundInstance = true; break; case (short)KnownElements.StaticExtension: // Note that this assumes that StaticExtension has a default // constructor and one public property of type string and one // internal property of type object for optimized member info. instance = new StaticExtension((string)param); foundInstance = true; break; case (short)KnownElements.TemplateBindingExtension: // Note that this assumes that TemplateBindingExtension has a // constructor with one param of type DependencyProperty. If a // string is passed in due to there being other attributes like // converter being set, then that needs to be converted now first. DependencyProperty dp = param as DependencyProperty; if (dp == null) { string paramString = param as string; Type ownerType = ParserContext.TargetType; Debug.Assert(paramString != null); dp = XamlTypeMapper.ParsePropertyName(ParserContext, paramString.Trim(), ref ownerType); if (dp == null) { ThrowException(SRID.ParserNoDPOnOwner, paramString, ownerType.FullName); } } instance = new TemplateBindingExtension(dp); foundInstance = true; break; } } else { paramList = (ArrayList)CurrentContext.ObjectData; paramCount = paramList.Count; } if (!foundInstance) { // Find the constructor based on the number of parameters stored in paramList XamlTypeMapper.ConstructorData data = XamlTypeMapper.GetConstructors(elementType); ConstructorInfo[] infos = data.Constructors; for (int i=0; i<infos.Length; i++) { ConstructorInfo info = infos[i]; ParameterInfo[] paramInfos = data.GetParameters(i); if (paramInfos.Length == paramCount) { object[] paramArray = new object[paramInfos.Length]; if (paramCount == 1) { Debug.Assert(param != null && paramList == null, "Must have a single param"); ProcessConstructorParameter(paramInfos[0], param, ref paramArray[0]); // Fast code path for other markupextensions if (positiveElementTypeId == (short)KnownElements.RelativeSource) { // Note that this assumes that RelativeSource has a // constructor with one param of type RelativeSourceMode. instance = new System.Windows.Data.RelativeSource((System.Windows.Data.RelativeSourceMode)paramArray[0]); foundInstance = true; } } else { Debug.Assert(param == null && paramList != null, "Must have a paramList"); // Check each type and attempt to convert the paramList using // the type converter associated with each parameter type. for (int j=0; j<paramInfos.Length; j++) { ProcessConstructorParameter(paramInfos[j], paramList[j], ref paramArray[j]); } } if (!foundInstance) { // If we make it to here we have a list of converted parameters, so // invoke the constructor with that list. #if !STRESS try { #endif instance = info.Invoke(paramArray); foundInstance = true; #if !STRESS } catch (Exception e) { if (CriticalExceptions.IsCriticalException(e) || e is XamlParseException) { throw; } TargetInvocationException tie = e as TargetInvocationException; if( tie != null ) { e = tie.InnerException; } ThrowExceptionWithLine(SR.Get(SRID.ParserFailedToCreateFromConstructor, info.DeclaringType.Name), e); } #endif } } } } if (foundInstance) { ParentContext.ObjectData = instance; ParentContext.ExpectedType = null; PopContext(); } else { // If we get to here, then no matching constructor was found, so complain ThrowException(SRID.ParserBadConstructorParams, elementType.Name, paramCount.ToString(CultureInfo.CurrentCulture)); } if( TraceMarkup.IsEnabled ) { TraceMarkup.Trace( TraceEventType.Stop, TraceMarkup.CreateMarkupExtension, elementType, instance ); } }