Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WF / Common / AuthoringOM / Serializer / WorkflowMarkupSerializer.cs / 1305376 / WorkflowMarkupSerializer.cs
namespace System.Workflow.ComponentModel.Serialization { using System; using System.IO; using System.CodeDom; using System.ComponentModel; using System.ComponentModel.Design; using System.ComponentModel.Design.Serialization; using System.Collections; using System.Xml; using System.Xml.Serialization; using System.Reflection; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Globalization; using System.Workflow.ComponentModel.Compiler; using System.Workflow.ComponentModel.Design; using System.Runtime.Serialization; using System.Security.Permissions; using System.Collections.ObjectModel; using System.Drawing; using System.Diagnostics.CodeAnalysis; #region Class WorkflowMarkupSerializer //Main serialization class for persisting the XOML [DefaultSerializationProvider(typeof(WorkflowMarkupSerializationProvider))] public class WorkflowMarkupSerializer { // x:Class & x:Code property. public so it can be set from outside. public static readonly DependencyProperty XClassProperty = DependencyProperty.RegisterAttached("XClass", typeof(string), typeof(WorkflowMarkupSerializer), new PropertyMetadata(DependencyPropertyOptions.Metadata, new Attribute[] { new BrowsableAttribute(false), new DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden) })); public static readonly DependencyProperty XCodeProperty = DependencyProperty.RegisterAttached("XCode", typeof(CodeTypeMemberCollection), typeof(WorkflowMarkupSerializer), new PropertyMetadata(DependencyPropertyOptions.Metadata, new Attribute[] { new BrowsableAttribute(false), new DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden) })); public static readonly DependencyProperty EventsProperty = DependencyProperty.RegisterAttached("Events", typeof(Hashtable), typeof(WorkflowMarkupSerializer), new PropertyMetadata(null, new Attribute[] { new DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden) })); public static readonly DependencyProperty ClrNamespacesProperty = DependencyProperty.RegisterAttached("ClrNamespaces", typeof(List), typeof(WorkflowMarkupSerializer), new PropertyMetadata(null, new Attribute[] { new DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden) })); #region Public Methods public object Deserialize(XmlReader reader) { if (reader == null) throw new ArgumentNullException("reader"); DesignerSerializationManager designerSerializationManager = new DesignerSerializationManager(); using (designerSerializationManager.CreateSession()) { return Deserialize(designerSerializationManager, reader); } } public object Deserialize(IDesignerSerializationManager serializationManager, XmlReader reader) { if (serializationManager == null) throw new ArgumentNullException("serializationManager"); if (reader == null) throw new ArgumentNullException("reader"); WorkflowMarkupSerializationManager markupSerializationManager = serializationManager as WorkflowMarkupSerializationManager; if (markupSerializationManager == null) markupSerializationManager = new WorkflowMarkupSerializationManager(serializationManager); string fileName = markupSerializationManager.Context[typeof(string)] as string; if (fileName == null) fileName = String.Empty; markupSerializationManager.FoundDefTag += delegate(object sender, WorkflowMarkupElementEventArgs eventArgs) { if (eventArgs.XmlReader.LookupNamespace(eventArgs.XmlReader.Prefix) == StandardXomlKeys.Definitions_XmlNs) WorkflowMarkupSerializationHelpers.ProcessDefTag(markupSerializationManager, eventArgs.XmlReader, markupSerializationManager.Context.Current as Activity, false, fileName); }; object obj = DeserializeXoml(markupSerializationManager, reader); // Copy the mappingPI to schedule user data Activity rootActivity = obj as Activity; if (rootActivity != null) { List clrMappings = rootActivity.GetValue(WorkflowMarkupSerializer.ClrNamespacesProperty) as List ; if (clrMappings == null) { clrMappings = new List (); rootActivity.SetValue(WorkflowMarkupSerializer.ClrNamespacesProperty, clrMappings); } foreach (WorkflowMarkupSerializerMapping mapping in markupSerializationManager.ClrNamespaceBasedMappings.Values) clrMappings.Add(mapping.ClrNamespace); rootActivity.SetValue(ActivityCodeDomSerializer.MarkupFileNameProperty, fileName); // If Name is not set and there is an XClass, set the name to that. if ((string.IsNullOrEmpty(rootActivity.Name) || rootActivity.Name == rootActivity.GetType().Name) && !string.IsNullOrEmpty(rootActivity.GetValue(WorkflowMarkupSerializer.XClassProperty) as string)) { string name = rootActivity.GetValue(WorkflowMarkupSerializer.XClassProperty) as string; if(name.Contains(".")) rootActivity.Name = name.Substring(name.LastIndexOf('.') + 1); else rootActivity.Name = name; } } return obj; } private object DeserializeXoml(WorkflowMarkupSerializationManager serializationManager, XmlReader xmlReader) { if (serializationManager == null) throw new ArgumentNullException("serializationManager"); if (xmlReader == null) throw new ArgumentNullException("xmlReader"); Object obj = null; //xmlReader.WhitespaceHandling = WhitespaceHandling.None; serializationManager.WorkflowMarkupStack.Push(xmlReader); try { // while (xmlReader.Read() && xmlReader.NodeType != XmlNodeType.Element && xmlReader.NodeType != XmlNodeType.ProcessingInstruction) ; if (xmlReader.EOF) return null; obj = DeserializeObject(serializationManager, xmlReader); // Read until the end of the xml stream i.e past the tag. // If there are any exceptions log them as errors. while (xmlReader.Read() && !xmlReader.EOF) ; } catch (XmlException xmlException) { throw new WorkflowMarkupSerializationException(xmlException.Message, xmlException, xmlException.LineNumber, xmlException.LinePosition); } catch (Exception e) { throw CreateSerializationError(e, xmlReader); } finally { serializationManager.WorkflowMarkupStack.Pop(); } return obj; } public void Serialize(XmlWriter writer, object obj) { if (obj == null) throw new ArgumentNullException("obj"); if (writer == null) throw new ArgumentNullException("writer"); DesignerSerializationManager designerSerializationManager = new DesignerSerializationManager(); using (designerSerializationManager.CreateSession()) { Serialize(designerSerializationManager, writer, obj); } } public void Serialize(IDesignerSerializationManager serializationManager, XmlWriter writer, object obj) { if (serializationManager == null) throw new ArgumentNullException("serializationManager"); if (obj == null) throw new ArgumentNullException("obj"); if (writer == null) throw new ArgumentNullException("writer"); WorkflowMarkupSerializationManager markupSerializationManager = serializationManager as WorkflowMarkupSerializationManager; if (markupSerializationManager == null) markupSerializationManager = new WorkflowMarkupSerializationManager(serializationManager); StringWriter xomlStringWriter = new StringWriter(CultureInfo.InvariantCulture); XmlWriter xmlWriter = Helpers.CreateXmlWriter(xomlStringWriter); markupSerializationManager.WorkflowMarkupStack.Push(xmlWriter); markupSerializationManager.WorkflowMarkupStack.Push(xomlStringWriter); try { SerializeObject(markupSerializationManager, obj, xmlWriter); } finally { xmlWriter.Close(); writer.WriteRaw(xomlStringWriter.ToString()); writer.Flush(); markupSerializationManager.WorkflowMarkupStack.Pop(); markupSerializationManager.WorkflowMarkupStack.Pop(); } } #endregion #region Protected Methods (Non-overridable) internal object DeserializeObject(WorkflowMarkupSerializationManager serializationManager, XmlReader reader) { if (serializationManager == null) throw new ArgumentNullException("serializationManager"); if (reader == null) throw new ArgumentNullException("reader"); object obj = null; try { serializationManager.WorkflowMarkupStack.Push(reader); AdvanceReader(reader); if (reader.NodeType != XmlNodeType.Element) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_InvalidDataFound), reader)); } else { // Lets ignore the Definition tags if nobody is interested // string decodedName = XmlConvert.DecodeName(reader.LocalName); XmlQualifiedName xmlQualifiedName = new XmlQualifiedName(decodedName, reader.LookupNamespace(reader.Prefix)); if (xmlQualifiedName.Namespace.Equals(StandardXomlKeys.Definitions_XmlNs, StringComparison.Ordinal) && !IsMarkupExtension(xmlQualifiedName) && !ExtendedPropertyInfo.IsExtendedProperty(serializationManager, xmlQualifiedName)) { int initialDepth = reader.Depth; serializationManager.FireFoundDefTag(new WorkflowMarkupElementEventArgs(reader)); if ((initialDepth + 1) < reader.Depth) { while (reader.Read() && (initialDepth + 1) < reader.Depth) ; } } else { obj = CreateInstance(serializationManager, xmlQualifiedName, reader); reader.MoveToElement(); if (obj != null) { serializationManager.Context.Push(obj); try { DeserializeContents(serializationManager, obj, reader); } finally { Debug.Assert(serializationManager.Context.Current == obj, "Serializer did not remove an object it pushed into stack."); serializationManager.Context.Pop(); } } } } } finally { serializationManager.WorkflowMarkupStack.Pop(); } return obj; } private void DeserializeContents(WorkflowMarkupSerializationManager serializationManager, object obj, XmlReader reader) { if (serializationManager == null) throw new ArgumentNullException("serializationManager"); if (obj == null) throw new ArgumentNullException("obj"); if (reader == null) throw new ArgumentNullException("reader"); if (reader.NodeType != XmlNodeType.Element) return; // get the serializer WorkflowMarkupSerializer serializer = serializationManager.GetSerializer(obj.GetType(), typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer; if (serializer == null) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerNotAvailable, obj.GetType().FullName), reader)); return; } try { serializer.OnBeforeDeserialize(serializationManager, obj); } catch (Exception e) { serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e)); return; } bool isEmptyElement = reader.IsEmptyElement; string elementNamespace = reader.NamespaceURI; List props = new List (); List events = new List (); // Add the extended properties for primitive types if (obj.GetType().IsPrimitive || obj.GetType() == typeof(string) || obj.GetType() == typeof(decimal) || obj.GetType().IsEnum || obj.GetType() == typeof(DateTime) || obj.GetType() == typeof(TimeSpan) || obj.GetType() == typeof(Guid)) { props.AddRange(serializationManager.GetExtendedProperties(obj)); } else { try { props.AddRange(serializer.GetProperties(serializationManager, obj)); props.AddRange(serializationManager.GetExtendedProperties(obj)); events.AddRange(serializer.GetEvents(serializationManager, obj)); } catch (Exception e) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerThrewException, obj.GetType(), e.Message), e, reader)); return; } } //First we try to deserialize simple properties if (reader.HasAttributes) { while (reader.MoveToNextAttribute()) { // if (reader.LocalName.Equals("xmlns", StringComparison.Ordinal) || reader.Prefix.Equals("xmlns", StringComparison.Ordinal)) continue; // XmlQualifiedName xmlQualifiedName = new XmlQualifiedName(reader.LocalName, reader.LookupNamespace(reader.Prefix)); if (xmlQualifiedName.Namespace.Equals(StandardXomlKeys.Definitions_XmlNs, StringComparison.Ordinal) && !IsMarkupExtension(xmlQualifiedName) && !ExtendedPropertyInfo.IsExtendedProperty(serializationManager, props, xmlQualifiedName) && !ExtendedPropertyInfo.IsExtendedProperty(serializationManager, xmlQualifiedName)) { serializationManager.FireFoundDefTag(new WorkflowMarkupElementEventArgs(reader)); continue; } //For simple properties we assume that if . indicates string propName =XmlConvert.DecodeName(reader.LocalName); string propVal = reader.Value; DependencyProperty dependencyProperty = ResolveDependencyProperty(serializationManager, reader, obj, propName); if (dependencyProperty != null) { serializationManager.Context.Push(dependencyProperty); try { if (dependencyProperty.IsEvent) DeserializeEvent(serializationManager, reader, obj, propVal); else DeserializeSimpleProperty(serializationManager, reader, obj, propVal); } finally { Debug.Assert(serializationManager.Context.Current == dependencyProperty, "Serializer did not remove an object it pushed into stack."); serializationManager.Context.Pop(); } } else { PropertyInfo property = WorkflowMarkupSerializer.LookupProperty(props, propName); if (property != null) { serializationManager.Context.Push(property); try { DeserializeSimpleProperty(serializationManager, reader, obj, propVal); } finally { Debug.Assert((PropertyInfo)serializationManager.Context.Current == property, "Serializer did not remove an object it pushed into stack."); serializationManager.Context.Pop(); } } else { EventInfo evt = WorkflowMarkupSerializer.LookupEvent(events, propName); if (events != null && evt != null) { serializationManager.Context.Push(evt); try { DeserializeEvent(serializationManager, reader, obj, propVal); } finally { Debug.Assert((EventInfo)serializationManager.Context.Current == evt, "Serializer did not remove an object it pushed into stack."); serializationManager.Context.Pop(); } } else serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerNoMemberFound, new object[] { propName, obj.GetType().FullName }), reader)); } } } } try { serializer.OnBeforeDeserializeContents(serializationManager, obj); } catch (Exception e) { serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e)); return; } //Now deserialize compound properties try { serializer.ClearChildren(serializationManager, obj); } catch(Exception e) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerThrewException, obj.GetType(), e.Message), e, reader)); return; } using (ContentProperty contentProperty = new ContentProperty(serializationManager, serializer, obj)) { List contents = new List (); if (!isEmptyElement) { reader.MoveToElement(); int initialDepth = reader.Depth; XmlQualifiedName extendedPropertyQualifiedName = new XmlQualifiedName(reader.LocalName, reader.LookupNamespace(reader.Prefix)); do { // Extended property should be deserialized, this is required for primitive types which have extended property as children // We should not ignore if (extendedPropertyQualifiedName != null && !ExtendedPropertyInfo.IsExtendedProperty(serializationManager, extendedPropertyQualifiedName)) { extendedPropertyQualifiedName = null; continue; } // this will make it to skip all the nodes if ((initialDepth + 1) < reader.Depth) { bool unnecessaryXmlFound = false; while (reader.Read() && ((initialDepth + 1) < reader.Depth)) { // Ignore comments and whitespaces if (reader.NodeType != XmlNodeType.Comment && reader.NodeType != XmlNodeType.Whitespace && !unnecessaryXmlFound) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_InvalidDataFoundForType, obj.GetType().FullName), reader)); unnecessaryXmlFound = true; } } } //Push all the PIs into stack so that they are available for type resolution AdvanceReader(reader); if (reader.NodeType == XmlNodeType.Element) { //We should only support A.B syntax for compound properties, all others are treated as content XmlQualifiedName xmlQualifiedName = new XmlQualifiedName(reader.LocalName, reader.LookupNamespace(reader.Prefix)); int index = reader.LocalName.IndexOf('.'); if (index > 0 || ExtendedPropertyInfo.IsExtendedProperty(serializationManager, xmlQualifiedName)) { string propertyName = reader.LocalName.Substring(reader.LocalName.IndexOf('.') + 1); PropertyInfo property = WorkflowMarkupSerializer.LookupProperty(props, propertyName); DependencyProperty dependencyProperty = ResolveDependencyProperty(serializationManager, reader, obj, reader.LocalName); if(dependencyProperty == null && property == null) serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_InvalidElementFoundForType, reader.LocalName, obj.GetType().FullName), reader)); else if (dependencyProperty != null) { PropertyInfo prop = WorkflowMarkupSerializer.LookupProperty(props, dependencyProperty.Name); //Deserialize the dynamic property serializationManager.Context.Push(dependencyProperty); try { DeserializeCompoundProperty(serializationManager, reader, obj); } finally { Debug.Assert(serializationManager.Context.Current == dependencyProperty, "Serializer did not remove an object it pushed into stack."); serializationManager.Context.Pop(); } } else if (property != null) { //Deserialize the compound property serializationManager.Context.Push(property); try { DeserializeCompoundProperty(serializationManager, reader, obj); } finally { Debug.Assert((PropertyInfo)serializationManager.Context.Current == property, "Serializer did not remove an object it pushed into stack."); serializationManager.Context.Pop(); } } } else { //Deserialize the children int lineNumber = (reader is IXmlLineInfo) ? ((IXmlLineInfo)reader).LineNumber : 1; int linePosition = (reader is IXmlLineInfo) ? ((IXmlLineInfo)reader).LinePosition : 1; object obj2 = DeserializeObject(serializationManager, reader); if (obj2 != null) { obj2 = GetValueFromMarkupExtension(serializationManager, obj2); if (obj2 != null && obj2.GetType() == typeof(string) && ((string)obj2).StartsWith("{}", StringComparison.Ordinal)) obj2 = ((string)obj2).Substring(2); contents.Add(new ContentInfo(obj2, lineNumber, linePosition)); } } } else if (reader.NodeType == XmlNodeType.Text && contentProperty.Property != null) { //If we read the string then we should not advance the reader further instead break int lineNumber = (reader is IXmlLineInfo) ? ((IXmlLineInfo)reader).LineNumber : 1; int linePosition = (reader is IXmlLineInfo) ? ((IXmlLineInfo)reader).LinePosition : 1; contents.Add(new ContentInfo(reader.ReadString(), lineNumber, linePosition)); if (initialDepth >= reader.Depth) break; } else { if (reader.NodeType == XmlNodeType.Entity || reader.NodeType == XmlNodeType.Text || reader.NodeType == XmlNodeType.CDATA) serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_InvalidDataFound, reader.Value.Trim(), obj.GetType().FullName), reader)); } } while (reader.Read() && initialDepth < reader.Depth); } //Make sure that we set contents contentProperty.SetContents(contents); } try { serializer.OnAfterDeserialize(serializationManager, obj); } catch (Exception e) { serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e)); return; } } internal void SerializeObject(WorkflowMarkupSerializationManager serializationManager, object obj, XmlWriter writer) { if (serializationManager == null) throw new ArgumentNullException("serializationManager"); if (obj == null) throw new ArgumentNullException("obj"); if (writer == null) throw new ArgumentNullException("writer"); try { serializationManager.WorkflowMarkupStack.Push(writer); using (new SafeXmlNodeWriter(serializationManager, obj, null, XmlNodeType.Element)) { DictionaryEntry? entry = null; if (serializationManager.WorkflowMarkupStack[typeof(DictionaryEntry)] != null) entry = (DictionaryEntry)serializationManager.WorkflowMarkupStack[typeof(DictionaryEntry)]; // To handle the case when the key and value are same in the dictionary bool key = entry.HasValue && ((!entry.Value.GetType().IsValueType && entry.Value.Key == entry.Value.Value && entry.Value.Value == obj) || (entry.Value.GetType().IsValueType && entry.Value.Key.Equals(entry.Value.Value) && entry.Value.Value.Equals(obj))) && serializationManager.SerializationStack.Contains(obj); if (key || !serializationManager.SerializationStack.Contains(obj)) { serializationManager.Context.Push(obj); serializationManager.SerializationStack.Push(obj); try { SerializeContents(serializationManager, obj, writer, key); } finally { Debug.Assert(serializationManager.Context.Current == obj, "Serializer did not remove an object it pushed into stack."); serializationManager.Context.Pop(); serializationManager.SerializationStack.Pop(); } } else throw new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerStackOverflow, obj.ToString(), obj.GetType().FullName), 0, 0); } } finally { serializationManager.WorkflowMarkupStack.Pop(); } } internal void SerializeContents(WorkflowMarkupSerializationManager serializationManager, object obj, XmlWriter writer, bool dictionaryKey) { if (serializationManager == null) throw new ArgumentNullException("serializationManager"); if (obj == null) throw new ArgumentNullException("obj"); if (writer == null) throw new ArgumentNullException("writer"); WorkflowMarkupSerializer serializer = null; try { //Now get the serializer to persist the properties, if the serializer is not found then we dont serialize the properties serializer = serializationManager.GetSerializer(obj.GetType(), typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer; } catch (Exception e) { serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e)); return; } if (serializer == null) { serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerNotAvailableForSerialize, obj.GetType().FullName))); return; } try { serializer.OnBeforeSerialize(serializationManager, obj); } catch (Exception e) { serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e)); return; } Hashtable allProperties = new Hashtable(); ArrayList complexProperties = new ArrayList(); IDictionary dependencyProperties = null; List properties = new List (); List events = new List (); Hashtable designTimeTypeNames = null; // Serialize the extended properties for primitive types also if (obj.GetType().IsPrimitive || obj.GetType() == typeof(string) || obj.GetType() == typeof(decimal) || obj.GetType() == typeof(DateTime) || obj.GetType() == typeof(TimeSpan) || obj.GetType().IsEnum || obj.GetType() == typeof(Guid)) { if (obj.GetType() == typeof(char) || obj.GetType() == typeof(byte) || obj.GetType() == typeof(System.Int16) || obj.GetType() == typeof(decimal) || obj.GetType() == typeof(DateTime) || obj.GetType() == typeof(TimeSpan) || obj.GetType().IsEnum || obj.GetType() == typeof(Guid)) { //These non CLS-compliant are not supported in the XmlWriter if ((obj.GetType() != typeof(char)) || (char)obj != '\0') { //These non CLS-compliant are not supported in the XmlReader string stringValue = String.Empty; if (obj.GetType() == typeof(DateTime)) { stringValue = ((DateTime)obj).ToString("o", CultureInfo.InvariantCulture); } else { TypeConverter typeConverter = TypeDescriptor.GetConverter(obj.GetType()); if (typeConverter != null && typeConverter.CanConvertTo(typeof(string))) stringValue = typeConverter.ConvertTo(null, CultureInfo.InvariantCulture, obj, typeof(string)) as string; else stringValue = Convert.ToString(obj, CultureInfo.InvariantCulture); } writer.WriteValue(stringValue); } } else if (obj.GetType() == typeof(string)) { string attribValue = obj as string; attribValue = attribValue.Replace('\0', ' '); if (!(attribValue.StartsWith("{", StringComparison.Ordinal) && attribValue.EndsWith("}", StringComparison.Ordinal))) writer.WriteValue(attribValue); else writer.WriteValue("{}" + attribValue); } else { writer.WriteValue(obj); } // For Key properties, we don;t want to get the extended properties if(!dictionaryKey) properties.AddRange(serializationManager.GetExtendedProperties(obj)); } else { // Serialize properties //We first get all the properties, once we have them all, we start distinguishing between //simple and complex properties, the reason for that is XmlWriter needs to write attributes //first and elements later // Dependency events are treated as the same as dependency properties. try { if (obj is DependencyObject && ((DependencyObject)obj).UserData.Contains(UserDataKeys.DesignTimeTypeNames)) designTimeTypeNames = ((DependencyObject)obj).UserData[UserDataKeys.DesignTimeTypeNames] as Hashtable; dependencyProperties = serializer.GetDependencyProperties(serializationManager, obj); properties.AddRange(serializer.GetProperties(serializationManager, obj)); // For Key properties, we don;t want to get the extended properties if (!dictionaryKey) properties.AddRange(serializationManager.GetExtendedProperties(obj)); events.AddRange(serializer.GetEvents(serializationManager, obj)); } catch (Exception e) { serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e)); return; } } if (dependencyProperties != null) { // For attached properties that does not have a corresponding real property on the object, if the value is a design time // type, it may not be set through dependency property SetValue, therefore will not be present in the dependencyProperties // collection, we'll have to get the dependency property object ourselves. if (designTimeTypeNames != null) { foreach (object key in designTimeTypeNames.Keys) { DependencyProperty dependencyProperty = key as DependencyProperty; if (dependencyProperty != null && !dependencyProperties.ContainsKey(dependencyProperty)) dependencyProperties.Add(dependencyProperty, designTimeTypeNames[dependencyProperty]); } } // Add all dependency properties to the master collection. foreach (DependencyProperty dependencyProperty in dependencyProperties.Keys) { string propertyName = String.Empty; if (dependencyProperty.IsAttached) { string prefix = String.Empty; XmlQualifiedName qualifiedName = serializationManager.GetXmlQualifiedName(dependencyProperty.OwnerType, out prefix); propertyName = qualifiedName.Name + "." + dependencyProperty.Name; } else { propertyName = dependencyProperty.Name; } if (dependencyProperty.IsAttached || !dependencyProperty.DefaultMetadata.IsMetaProperty) allProperties.Add(propertyName, dependencyProperty); } } if (properties != null) { foreach (PropertyInfo propInfo in properties) { // Do not serialize properties that have corresponding dynamic properties. if (propInfo != null && !allProperties.ContainsKey(propInfo.Name)) allProperties.Add(propInfo.Name, propInfo); } } if (events != null) { foreach (EventInfo eventInfo in events) { // Do not serialize events that have corresponding dynamic properties. if (eventInfo != null && !allProperties.ContainsKey(eventInfo.Name)) allProperties.Add(eventInfo.Name, eventInfo); } } using (ContentProperty contentProperty = new ContentProperty(serializationManager, serializer, obj)) { foreach (object propertyObj in allProperties.Values) { string propertyName = String.Empty; object propertyValue = null; Type propertyInfoType = null; try { if (propertyObj is PropertyInfo) { PropertyInfo property = propertyObj as PropertyInfo; // If the property has parameters we can not serialize it , we just move on. ParameterInfo[] indexParameters = property.GetIndexParameters(); if (indexParameters != null && indexParameters.Length > 0) continue; propertyName = property.Name; propertyValue = null; if (property.CanRead) { propertyValue = property.GetValue(obj, null); if (propertyValue == null && TypeProvider.IsAssignable(typeof(Type), property.PropertyType)) { // See if we have a design time value for the property DependencyProperty dependencyProperty = DependencyProperty.FromName(property.Name, property.ReflectedType); if (dependencyProperty != null) propertyValue = Helpers.GetDesignTimeTypeName(obj, dependencyProperty); if (propertyValue == null) { string key = property.ReflectedType.FullName + "." + property.Name; propertyValue = Helpers.GetDesignTimeTypeName(obj, key); } if (propertyValue != null) propertyValue = new TypeExtension((string)propertyValue); } } propertyInfoType = property.PropertyType; } else if (propertyObj is EventInfo) { EventInfo evt = propertyObj as EventInfo; propertyName = evt.Name; propertyValue = WorkflowMarkupSerializationHelpers.GetEventHandlerName(obj, evt.Name); if ((propertyValue == null || (propertyValue is string && string.IsNullOrEmpty((string)propertyValue))) && obj is DependencyObject) { // The object is not created through deserialization, we should check to see if the delegate is // created and added to list. We can only serialize the handler if its target type is the same // as the activity type that's be designed. DependencyProperty dependencyProperty = DependencyProperty.FromName(propertyName, obj.GetType()); if (dependencyProperty != null) { Activity activity = serializationManager.Context[typeof(Activity)] as Activity; Delegate handler = ((DependencyObject)obj).GetHandler(dependencyProperty) as Delegate; if (handler != null && activity != null && TypeProvider.Equals(handler.Target.GetType(), Helpers.GetRootActivity(activity).GetType())) propertyValue = handler; } } propertyInfoType = evt.EventHandlerType; } else if (propertyObj is DependencyProperty) { DependencyProperty dependencyProperty = propertyObj as DependencyProperty; propertyName = dependencyProperty.Name; propertyValue = dependencyProperties[dependencyProperty]; propertyInfoType = dependencyProperty.PropertyType; } } catch(Exception e) { while (e is TargetInvocationException && e.InnerException != null) e = e.InnerException; serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerPropertyGetFailed, new object[] { propertyName, obj.GetType().FullName, e.Message }))); continue; } if (propertyObj is PropertyInfo && contentProperty.Property == (PropertyInfo)propertyObj) continue; Type propertyValueType = null; if (propertyValue != null) { propertyValue = GetMarkupExtensionFromValue(propertyValue); propertyValueType = propertyValue.GetType(); } else if (propertyObj is PropertyInfo) { propertyValue = new NullExtension(); propertyValueType = propertyValue.GetType(); Attribute[] attributes = Attribute.GetCustomAttributes(propertyObj as PropertyInfo, typeof(DefaultValueAttribute), true); if (attributes.Length > 0) { DefaultValueAttribute defaultValueAttr = attributes[0] as DefaultValueAttribute; if (defaultValueAttr.Value == null) propertyValue = null; } } if (propertyValue != null) propertyValueType = propertyValue.GetType(); //Now get the serializer to persist the properties, if the serializer is not found then we dont serialize the properties serializationManager.Context.Push(propertyObj); WorkflowMarkupSerializer propValueSerializer = null; try { propValueSerializer = serializationManager.GetSerializer(propertyValueType, typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer; } catch (Exception e) { serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e)); serializationManager.Context.Pop(); continue; } if (propValueSerializer == null) { serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerNotAvailableForSerialize, propertyValueType.FullName))); serializationManager.Context.Pop(); continue; } // ask serializer if we can serialize try { if (propValueSerializer.ShouldSerializeValue(serializationManager, propertyValue)) { //NOTE: THE FOLLOWING CONDITION ABOUT propertyInfoType != typeof(object) is VALID AS WE SHOULD NOT SERIALIZE A PROPERTY OF TYPE OBJECT TO STRING //IF WE DO THAT THEN WE DO NOT KNOWN WHAT WAS THE TYPE OF ORIGINAL OBJECT AND SERIALIZER WONT BE ABLE TO GET THE STRING BACK INTO THE CORRECT TYPE, //AS THE TYPE INFORMATION IS LOST if (propValueSerializer.CanSerializeToString(serializationManager, propertyValue) && propertyInfoType != typeof(object)) { using (new SafeXmlNodeWriter(serializationManager, obj, propertyObj, XmlNodeType.Attribute)) { //This is a work around to special case the markup extension serializer as it writes to the stream using writer if (propValueSerializer is MarkupExtensionSerializer) { propValueSerializer.SerializeToString(serializationManager, propertyValue); } else { string stringValue = propValueSerializer.SerializeToString(serializationManager, propertyValue); if (!string.IsNullOrEmpty(stringValue)) { stringValue = stringValue.Replace('\0', ' '); if (propertyValue is MarkupExtension || !(stringValue.StartsWith("{", StringComparison.Ordinal) && stringValue.EndsWith("}", StringComparison.Ordinal))) writer.WriteString(stringValue); else writer.WriteString("{}" + stringValue); } } } } else { complexProperties.Add(propertyObj); } } } catch (Exception e) { serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerNoSerializeLogic, new object[] { propertyName, obj.GetType().FullName }), e)); } finally { Debug.Assert(serializationManager.Context.Current == propertyObj, "Serializer did not remove an object it pushed into stack."); serializationManager.Context.Pop(); } } try { serializer.OnBeforeSerializeContents(serializationManager, obj); } catch (Exception e) { serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e)); return; } // serialize compound properties as child elements of the current node. foreach (object propertyObj in complexProperties) { // get value and check for null string propertyName = String.Empty; object propertyValue = null; Type ownerType = null; bool isReadOnly = false; try { if (propertyObj is PropertyInfo) { PropertyInfo property = propertyObj as PropertyInfo; propertyName = property.Name; propertyValue = property.CanRead ? property.GetValue(obj, null) : null; ownerType = obj.GetType(); isReadOnly = (!property.CanWrite); } else if (propertyObj is DependencyProperty) { DependencyProperty dependencyProperty = propertyObj as DependencyProperty; propertyName = dependencyProperty.Name; propertyValue = dependencyProperties[dependencyProperty]; ownerType = dependencyProperty.OwnerType; isReadOnly = ((dependencyProperty.DefaultMetadata.Options & DependencyPropertyOptions.ReadOnly) == DependencyPropertyOptions.ReadOnly); } } catch(Exception e) { while (e is TargetInvocationException && e.InnerException != null) e = e.InnerException; serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerPropertyGetFailed, propertyName, ownerType.FullName, e.Message))); continue; } if (propertyObj is PropertyInfo && (PropertyInfo)propertyObj == contentProperty.Property) continue; if (propertyValue != null) { propertyValue = GetMarkupExtensionFromValue(propertyValue); WorkflowMarkupSerializer propValueSerializer = serializationManager.GetSerializer(propertyValue.GetType(), typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer; if (propValueSerializer != null) { using (new SafeXmlNodeWriter(serializationManager, obj, propertyObj, XmlNodeType.Element)) { if (isReadOnly) propValueSerializer.SerializeContents(serializationManager, propertyValue, writer, false); else propValueSerializer.SerializeObject(serializationManager, propertyValue, writer); } } else { serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerNotAvailableForSerialize, propertyValue.GetType().FullName))); } } } // serialize the contents try { object contents = contentProperty.GetContents(); if (contents != null) { contents = GetMarkupExtensionFromValue(contents); WorkflowMarkupSerializer propValueSerializer = serializationManager.GetSerializer(contents.GetType(), typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer; if (propValueSerializer == null) { serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerNotAvailableForSerialize, contents.GetType()))); } else { // //NOTE: THE FOLLOWING CONDITION ABOUT contentProperty.Property.PropertyType != typeof(object) is VALID AS WE SHOULD NOT SERIALIZE A PROPERTY OF TYPE OBJECT TO STRING //IF WE DO THAT THEN WE DO NOT KNOWN WHAT WAS THE TYPE OF ORIGINAL OBJECT AND SERIALIZER WONT BE ABLE TO GET THE STRING BACK INTO THE CORRECT TYPE, //AS THE TYPE INFORMATION IS LOST if (propValueSerializer.CanSerializeToString(serializationManager, contents) && (contentProperty.Property == null || contentProperty.Property.PropertyType != typeof(object))) { string stringValue = propValueSerializer.SerializeToString(serializationManager, contents); if (!string.IsNullOrEmpty(stringValue)) { stringValue = stringValue.Replace('\0', ' '); if (contents is MarkupExtension || !(stringValue.StartsWith("{", StringComparison.Ordinal) && stringValue.EndsWith("}", StringComparison.Ordinal))) writer.WriteString(stringValue); else writer.WriteString("{}" + stringValue); } } else if (CollectionMarkupSerializer.IsValidCollectionType(contents.GetType())) { if (contentProperty.Property == null) { IEnumerable enumerableContents = contents as IEnumerable; foreach (object childObj in enumerableContents) { if (childObj == null) { SerializeObject(serializationManager, new NullExtension(), writer); } else { object childObj2 = childObj; bool dictionaryEntry = (childObj2 is DictionaryEntry); try { if (dictionaryEntry) { serializationManager.WorkflowMarkupStack.Push(childObj); childObj2 = ((DictionaryEntry)childObj2).Value; } childObj2 = GetMarkupExtensionFromValue(childObj2); WorkflowMarkupSerializer childObjectSerializer = serializationManager.GetSerializer(childObj2.GetType(), typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer; if (childObjectSerializer != null) childObjectSerializer.SerializeObject(serializationManager, childObj2, writer); else serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerNotAvailableForSerialize, childObj2.GetType()))); } finally { if (dictionaryEntry) serializationManager.WorkflowMarkupStack.Pop(); } } } } else { propValueSerializer.SerializeContents(serializationManager, contents, writer, false); } } else { propValueSerializer.SerializeObject(serializationManager, contents, writer); } } } } catch (Exception e) { serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e)); return; } } try { serializer.OnAfterSerialize(serializationManager, obj); } catch (Exception e) { serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e)); return; } } #endregion #region Overridable Methods protected virtual void OnBeforeSerialize(WorkflowMarkupSerializationManager serializationManager, object obj) { } internal virtual void OnBeforeSerializeContents(WorkflowMarkupSerializationManager serializationManager, object obj) { } protected virtual void OnAfterSerialize(WorkflowMarkupSerializationManager serializationManager, object obj) { } protected virtual void OnBeforeDeserialize(WorkflowMarkupSerializationManager serializationManager, object obj) { } internal virtual void OnBeforeDeserializeContents(WorkflowMarkupSerializationManager serializationManager, object obj) { } protected virtual void OnAfterDeserialize(WorkflowMarkupSerializationManager serializationManager, object obj) { } protected internal virtual bool ShouldSerializeValue(WorkflowMarkupSerializationManager serializationManager, object value) { if (serializationManager == null) throw new ArgumentNullException("serializationManager"); if (value == null) return false; try { PropertyInfo property = serializationManager.Context.Current as PropertyInfo; if (property != null) { Attribute[] attributes = Attribute.GetCustomAttributes(property, typeof(DefaultValueAttribute), true); if (attributes.Length > 0) { DefaultValueAttribute defaultValueAttr = attributes[0] as DefaultValueAttribute; if (defaultValueAttr.Value is IConvertible && value is IConvertible && object.Equals(Convert.ChangeType(defaultValueAttr.Value, property.PropertyType, CultureInfo.InvariantCulture), Convert.ChangeType(value, property.PropertyType, CultureInfo.InvariantCulture))) return false; } } } catch { //We purposely eat all the exceptions as Convert.ChangeType can throw but in that case //we continue with serialization } return true; } protected internal virtual bool CanSerializeToString(WorkflowMarkupSerializationManager serializationManager, object value) { if (serializationManager == null) throw new ArgumentNullException("serializationManager"); if (value == null) throw new ArgumentNullException("value"); Type valueType = value.GetType(); if (valueType.IsPrimitive || valueType == typeof(System.String) || valueType.IsEnum || typeof(Delegate).IsAssignableFrom(valueType) || typeof(IConvertible).IsAssignableFrom(valueType) || valueType == typeof(TimeSpan) || valueType == typeof(Guid) || valueType == typeof(DateTime)) return true; return false; } protected internal virtual string SerializeToString(WorkflowMarkupSerializationManager serializationManager, object value) { if (serializationManager == null) throw new ArgumentNullException("serializationManager"); if (value == null) throw new ArgumentNullException("value"); if (typeof(Delegate).IsAssignableFrom(value.GetType())) return ((Delegate)value).Method.Name; else if (typeof(DateTime).IsAssignableFrom(value.GetType())) return ((DateTime)value).ToString("o", CultureInfo.InvariantCulture); else return Convert.ToString(value, CultureInfo.InvariantCulture); } protected internal virtual object DeserializeFromString(WorkflowMarkupSerializationManager serializationManager, Type propertyType, string value) { return InternalDeserializeFromString(serializationManager, propertyType, value); } private object InternalDeserializeFromString(WorkflowMarkupSerializationManager serializationManager, Type propertyType, string value) { if (serializationManager == null) throw new ArgumentNullException("serializationManager"); if (propertyType == null) throw new ArgumentNullException("propertyType"); if (value == null) throw new ArgumentNullException("value"); object propVal = null; XmlReader reader = serializationManager.WorkflowMarkupStack[typeof(XmlReader)] as XmlReader; if (reader == null) { Debug.Assert(false, "XmlReader not available."); return null; } if (IsValidCompactAttributeFormat(value)) { propVal = DeserializeFromCompactFormat(serializationManager, reader, value); } else { if (value.StartsWith("{}", StringComparison.Ordinal)) value = value.Substring(2); // Check for Nullable types if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) { Type genericType = (Type)propertyType.GetGenericArguments()[0]; Debug.Assert(genericType != null); propertyType = genericType; } if (propertyType.IsPrimitive || propertyType == typeof(System.String)) { propVal = Convert.ChangeType(value, propertyType, CultureInfo.InvariantCulture); } else if (propertyType.IsEnum) { propVal = Enum.Parse(propertyType, value, true); } else if (typeof(Delegate).IsAssignableFrom(propertyType)) { // Just return the method name. This must happen after Bind syntax has been checked. propVal = value; } else if (typeof(TimeSpan) == propertyType) { propVal = TimeSpan.Parse(value, CultureInfo.InvariantCulture); } else if (typeof(DateTime) == propertyType) { propVal = DateTime.Parse(value, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind); } else if (typeof(Guid) == propertyType) { propVal = Utility.CreateGuid(value); } else if (typeof(Type).IsAssignableFrom(propertyType)) { propVal = serializationManager.GetType(value); if (propVal != null) { Type type = propVal as Type; if (type.IsPrimitive || type.IsEnum || type == typeof(System.String)) return type; } ITypeProvider typeProvider = serializationManager.GetService(typeof(ITypeProvider)) as ITypeProvider; if (typeProvider != null) { Type type = typeProvider.GetType(value); if (type != null) return type; } return value; } else if (typeof(IConvertible).IsAssignableFrom(propertyType)) { propVal = Convert.ChangeType(value, propertyType, CultureInfo.InvariantCulture); } else if (propertyType.IsAssignableFrom(value.GetType())) { propVal = value; } else { throw CreateSerializationError(SR.GetString(SR.Error_SerializerPrimitivePropertyNoLogic, new object[] { "", value.Trim(), "" }), reader); } } return propVal; } protected internal virtual IList GetChildren(WorkflowMarkupSerializationManager serializationManager, object obj) { if (serializationManager == null) throw new ArgumentNullException("serializationManager"); if (obj == null) throw new ArgumentNullException("obj"); return null; } protected internal virtual void ClearChildren(WorkflowMarkupSerializationManager serializationManager, object obj) { if (serializationManager == null) throw new ArgumentNullException("serializationManager"); if (obj == null) throw new ArgumentNullException("obj"); } protected internal virtual void AddChild(WorkflowMarkupSerializationManager serializationManager, object parentObject, object childObj) { if (serializationManager == null) throw new ArgumentNullException("serializationManager"); if (parentObject == null) throw new ArgumentNullException("parentObject"); if (childObj == null) throw new ArgumentNullException("childObj"); throw new Exception(SR.GetString(SR.Error_SerializerNoChildNotion, new object[] { parentObject.GetType().FullName })); } protected virtual object CreateInstance(WorkflowMarkupSerializationManager serializationManager, Type type) { if (serializationManager == null) throw new ArgumentNullException("serializationManager"); if (type == null) throw new ArgumentNullException("type"); return Activator.CreateInstance(type); } protected internal virtual PropertyInfo[] GetProperties(WorkflowMarkupSerializationManager serializationManager, object obj) { if (obj == null) throw new ArgumentNullException("obj"); if (serializationManager == null) throw new ArgumentNullException("serializationManager"); List properties = new List (); object[] attributes = obj.GetType().GetCustomAttributes(typeof(RuntimeNamePropertyAttribute), true); string name = null; if (attributes.Length > 0) name = (attributes[0] as RuntimeNamePropertyAttribute).Name; foreach (PropertyInfo property in obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy)) { DesignerSerializationVisibility visibility = Helpers.GetSerializationVisibility(property); if (visibility == DesignerSerializationVisibility.Hidden) continue; if (visibility != DesignerSerializationVisibility.Content && (!property.CanWrite || property.GetSetMethod() == null)) { // work around for CodeObject which are ICollection needs to be serialized. if(!(obj is CodeObject) || !typeof(ICollection).IsAssignableFrom(property.PropertyType)) continue; } TypeProvider typeProvider = serializationManager.GetService(typeof(ITypeProvider)) as TypeProvider; if (typeProvider != null) { if (!typeProvider.IsSupportedProperty(property, obj)) { continue; } } if(name == null || !name.Equals(property.Name)) properties.Add(property); else properties.Add(new ExtendedPropertyInfo(property, OnGetRuntimeNameValue, OnSetRuntimeNameValue, OnGetRuntimeQualifiedName)); } return properties.ToArray(); } protected internal virtual EventInfo[] GetEvents(WorkflowMarkupSerializationManager serializationManager, object obj) { if (obj == null) throw new ArgumentNullException("obj"); if (serializationManager == null) throw new ArgumentNullException("serializationManager"); List events = new List (); foreach (EventInfo evt in obj.GetType().GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy)) { if (Helpers.GetSerializationVisibility(evt) == DesignerSerializationVisibility.Hidden) continue; events.Add(evt); } return events.ToArray(); } internal virtual ExtendedPropertyInfo[] GetExtendedProperties(WorkflowMarkupSerializationManager manager, object extendee) { return new ExtendedPropertyInfo[0]; } private object OnGetRuntimeNameValue(ExtendedPropertyInfo extendedProperty, object extendee) { return extendedProperty.RealPropertyInfo.GetValue(extendee, null); } private void OnSetRuntimeNameValue(ExtendedPropertyInfo extendedProperty, object extendee, object value) { if (extendee != null && value != null) extendedProperty.RealPropertyInfo.SetValue(extendee, value, null); } private XmlQualifiedName OnGetRuntimeQualifiedName(ExtendedPropertyInfo extendedProperty, WorkflowMarkupSerializationManager manager, out string prefix) { prefix = StandardXomlKeys.Definitions_XmlNs_Prefix; return new XmlQualifiedName(extendedProperty.Name, StandardXomlKeys.Definitions_XmlNs); } #endregion #region Dependency Properties // private IDictionary GetDependencyProperties(WorkflowMarkupSerializationManager serializationManager, object obj) { if (serializationManager == null) throw new ArgumentNullException("serializationManager"); if (obj == null) throw new ArgumentNullException("obj"); List pis = new List (); pis.AddRange(GetProperties(serializationManager, obj)); List eis = new List (); eis.AddRange(GetEvents(serializationManager, obj)); Dictionary dependencyProperties = new Dictionary (); DependencyObject dependencyObject = obj as DependencyObject; if (dependencyObject != null) { foreach (DependencyProperty dependencyProperty in dependencyObject.MetaDependencyProperties) { Attribute[] visibilityAttrs = dependencyProperty.DefaultMetadata.GetAttributes(typeof(DesignerSerializationVisibilityAttribute)); if (visibilityAttrs.Length > 0 && ((DesignerSerializationVisibilityAttribute)visibilityAttrs[0]).Visibility == DesignerSerializationVisibility.Hidden) continue; //If the dependency property is readonly and we have not marked it with DesignerSerializationVisibility.Content attribute the we should not //serialize it if ((dependencyProperty.DefaultMetadata.Options & DependencyPropertyOptions.ReadOnly) == DependencyPropertyOptions.ReadOnly) { object[] serializationVisibilityAttribute = dependencyProperty.DefaultMetadata.GetAttributes(typeof(DesignerSerializationVisibilityAttribute)); if (serializationVisibilityAttribute == null || serializationVisibilityAttribute.Length == 0 || ((DesignerSerializationVisibilityAttribute)serializationVisibilityAttribute[0]).Visibility != DesignerSerializationVisibility.Content) { continue; } } object obj1 = null; if (!dependencyProperty.IsAttached && !dependencyProperty.DefaultMetadata.IsMetaProperty) { if (dependencyProperty.IsEvent) obj1 = LookupEvent(eis, dependencyProperty.Name); else obj1 = LookupProperty(pis, dependencyProperty.Name); if (obj1 == null) { serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_MissingCLRProperty, dependencyProperty.Name, obj.GetType().FullName))); continue; } } if (dependencyObject.IsBindingSet(dependencyProperty)) { dependencyProperties.Add(dependencyProperty, dependencyObject.GetBinding(dependencyProperty)); } else if (!dependencyProperty.IsEvent) { object propValue = null; propValue = dependencyObject.GetValue(dependencyProperty); if (!dependencyProperty.IsAttached && !dependencyProperty.DefaultMetadata.IsMetaProperty) { PropertyInfo propertyInfo = obj1 as PropertyInfo; // if the propertyValue is assignable to the type in of the .net property then call the .net property's getter also // else add the keep the value that we got if(propValue!=null && propertyInfo.PropertyType.IsAssignableFrom(propValue.GetType())) propValue = (obj1 as PropertyInfo).GetValue(dependencyObject, null); } dependencyProperties.Add(dependencyProperty, propValue); } else { dependencyProperties.Add(dependencyProperty, dependencyObject.GetHandler(dependencyProperty)); } } foreach (DependencyProperty dependencyProperty in dependencyObject.DependencyPropertyValues.Keys) { Attribute[] visibilityAttrs = dependencyProperty.DefaultMetadata.GetAttributes(typeof(DesignerSerializationVisibilityAttribute)); if (visibilityAttrs.Length > 0 && ((DesignerSerializationVisibilityAttribute)visibilityAttrs[0]).Visibility == DesignerSerializationVisibility.Hidden) continue; if (!dependencyProperty.DefaultMetadata.IsMetaProperty && dependencyProperty.IsAttached && VerifyAttachedPropertyConditions(dependencyProperty)) dependencyProperties.Add(dependencyProperty, dependencyObject.GetValue(dependencyProperty)); } } return dependencyProperties; } private static bool VerifyAttachedPropertyConditions(DependencyProperty dependencyProperty) { if (dependencyProperty.IsEvent) { if (dependencyProperty.OwnerType.GetField(dependencyProperty.Name + "Event", BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly) == null) return false; MethodInfo methodInfo = dependencyProperty.OwnerType.GetMethod("Add" + dependencyProperty.Name + "Handler", BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly); if (methodInfo == null) return false; ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters != null && parameters.Length == 2 && parameters[0].ParameterType == typeof(object) && parameters[1].ParameterType == typeof(object)) return true; } else { if (dependencyProperty.OwnerType.GetField(dependencyProperty.Name + "Property", BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly) == null) return false; MethodInfo methodInfo = dependencyProperty.OwnerType.GetMethod("Set" + dependencyProperty.Name, BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly); if (methodInfo == null) return false; ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters != null && parameters.Length == 2 && parameters[0].ParameterType == typeof(object) && parameters[1].ParameterType == typeof(object)) return true; } return false; } private void SetDependencyPropertyValue(WorkflowMarkupSerializationManager serializationManager, object obj, DependencyProperty dependencyProperty, object value) { if (dependencyProperty == null) throw new ArgumentNullException("dependencyProperty"); if (obj == null) throw new ArgumentNullException("obj"); DependencyObject dependencyObject = obj as DependencyObject; if (dependencyObject == null) throw new ArgumentException(SR.GetString(SR.Error_InvalidArgumentValue), "obj"); if (dependencyProperty.IsEvent) { if (value is ActivityBind) dependencyObject.SetBinding(dependencyProperty, value as ActivityBind); else if (dependencyProperty.IsAttached) { MethodInfo methodInfo = dependencyProperty.OwnerType.GetMethod("Add" + dependencyProperty.Name + "Handler", BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly); if (methodInfo != null) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters == null || parameters.Length != 2 || parameters[0].ParameterType != typeof(object) || parameters[1].ParameterType != typeof(object)) methodInfo = null; } if (methodInfo != null) WorkflowMarkupSerializationHelpers.SetEventHandlerName(dependencyObject, dependencyProperty.Name, value as string); else serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_MissingAddHandler, dependencyProperty.Name, dependencyProperty.OwnerType.FullName))); } else WorkflowMarkupSerializationHelpers.SetEventHandlerName(dependencyObject, dependencyProperty.Name, value as string); } else { if (value is ActivityBind) dependencyObject.SetBinding(dependencyProperty, value as ActivityBind); else if (value is string && TypeProvider.IsAssignable(typeof(Type), dependencyProperty.PropertyType)) Helpers.SetDesignTimeTypeName(obj, dependencyProperty, value as string); else if (dependencyProperty.IsAttached) { MethodInfo methodInfo = dependencyProperty.OwnerType.GetMethod("Set" + dependencyProperty.Name, BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly); if (methodInfo != null) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters == null || parameters.Length != 2 || parameters[0].ParameterType != typeof(object) || parameters[1].ParameterType != typeof(object)) methodInfo = null; } if (methodInfo != null) methodInfo.Invoke(null, new object[] { dependencyObject, value }); else serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_MissingSetAccessor, dependencyProperty.Name, dependencyProperty.OwnerType.FullName))); } else { List pis = new List (); pis.AddRange(GetProperties(serializationManager, obj)); //The following condition is workaround for the partner team as they depend on the dependencyObject.SetValue being called //for non assignable property values PropertyInfo pi = LookupProperty(pis, dependencyProperty.Name); if (pi != null && (value == null || pi.PropertyType.IsAssignableFrom(value.GetType()))) { if (pi.CanWrite) { pi.SetValue(obj, value, null); } else if(typeof(ICollection ).IsAssignableFrom(value.GetType())) { ICollection propVal = pi.GetValue(obj, null) as ICollection ; ICollection deserializedValue = value as ICollection ; if (propVal != null && deserializedValue != null) { foreach (string content in deserializedValue) propVal.Add(content); } } } else { dependencyObject.SetValue(dependencyProperty, value); } } } } #endregion #region Private Helpers #region Reader/Writer private void AdvanceReader(XmlReader reader) { //Compressed what process mapping pi used to do while (reader.NodeType != XmlNodeType.EndElement && reader.NodeType != XmlNodeType.Element && reader.NodeType != XmlNodeType.Text && reader.Read()) ; } #endregion #region Exception Handling internal static WorkflowMarkupSerializationException CreateSerializationError(Exception e, XmlReader reader) { return CreateSerializationError(null, e, reader); } internal static WorkflowMarkupSerializationException CreateSerializationError(string message, XmlReader reader) { return CreateSerializationError(message, null, reader); } internal static WorkflowMarkupSerializationException CreateSerializationError(string message, Exception e, XmlReader reader) { string errorMsg = message; if (string.IsNullOrEmpty(errorMsg)) errorMsg = e.Message; IXmlLineInfo xmlLineInfo = reader as IXmlLineInfo; if (xmlLineInfo != null) return new WorkflowMarkupSerializationException(errorMsg, xmlLineInfo.LineNumber, xmlLineInfo.LinePosition); else return new WorkflowMarkupSerializationException(errorMsg, 0, 0); } #endregion #region Type Creation Support private static string GetClrFullName(WorkflowMarkupSerializationManager serializationManager, XmlQualifiedName xmlQualifiedName) { string xmlns = xmlQualifiedName.Namespace; string typeName = xmlQualifiedName.Name; List xmlnsMappings = null; if (!serializationManager.XmlNamespaceBasedMappings.TryGetValue(xmlns, out xmlnsMappings) || xmlnsMappings.Count == 0) return xmlQualifiedName.Namespace + "." + xmlQualifiedName.Name; WorkflowMarkupSerializerMapping xmlnsMapping = xmlnsMappings[0]; string assemblyName = xmlnsMapping.AssemblyName; string dotNetnamespaceName = xmlnsMapping.ClrNamespace; // append dot net namespace name string fullTypeName = xmlQualifiedName.Name; if (dotNetnamespaceName.Length > 0) fullTypeName = (dotNetnamespaceName + "." + xmlQualifiedName.Name); return fullTypeName; } private object CreateInstance(WorkflowMarkupSerializationManager serializationManager, XmlQualifiedName xmlQualifiedName, XmlReader reader) { object obj = null; // resolve the type Type type = null; try { type = serializationManager.GetType(xmlQualifiedName); } catch (Exception e) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerTypeNotResolvedWithInnerError, new object[] { GetClrFullName(serializationManager, xmlQualifiedName), e.Message }), e, reader)); return null; } if (type == null && !xmlQualifiedName.Name.EndsWith("Extension", StringComparison.Ordinal)) { string typename = xmlQualifiedName.Name + "Extension"; try { type = serializationManager.GetType(new XmlQualifiedName(typename, xmlQualifiedName.Namespace)); } catch (Exception e) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerTypeNotResolvedWithInnerError, new object[] { GetClrFullName(serializationManager, xmlQualifiedName), e.Message }), e, reader)); return null; } } if (type == null) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerTypeNotResolved, new object[] { GetClrFullName(serializationManager, xmlQualifiedName) }), reader)); return null; } if (type.IsPrimitive || type == typeof(string) || type == typeof(decimal) || type == typeof(DateTime) || type == typeof(TimeSpan) || type.IsEnum || type == typeof(Guid)) { try { string stringValue = reader.ReadString(); if (type == typeof(DateTime)) { obj = DateTime.Parse(stringValue, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind); } else if (type.IsPrimitive || type == typeof(decimal) || type == typeof(TimeSpan) || type.IsEnum || type == typeof(Guid)) { //These non CLS-compliant are not supported in the XmlReader TypeConverter typeConverter = TypeDescriptor.GetConverter(type); if (typeConverter != null && typeConverter.CanConvertFrom(typeof(string))) obj = typeConverter.ConvertFrom(null, CultureInfo.InvariantCulture, stringValue); else if (typeof(IConvertible).IsAssignableFrom(type)) obj = Convert.ChangeType(stringValue, type, CultureInfo.InvariantCulture); } else { obj = stringValue; } } catch (Exception e) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerCreateInstanceFailed, e.Message), reader)); return null; } } else { // get the serializer WorkflowMarkupSerializer serializer = serializationManager.GetSerializer(type, typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer; if (serializer == null) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerNotAvailable, type.FullName), reader)); return null; } // create an instance try { obj = serializer.CreateInstance(serializationManager, type); } catch (Exception e) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerCreateInstanceFailed, type.FullName, e.Message), reader)); return null; } } return obj; } #endregion #region Simple and Complex property Serialization Support private void DeserializeCompoundProperty(WorkflowMarkupSerializationManager serializationManager, XmlReader reader, object obj) { string propertyName = reader.LocalName; bool isReadOnly = false; DependencyProperty dependencyProperty = serializationManager.Context.Current as DependencyProperty; PropertyInfo property = serializationManager.Context.Current as PropertyInfo; if (dependencyProperty != null) isReadOnly = ((dependencyProperty.DefaultMetadata.Options & DependencyPropertyOptions.ReadOnly) == DependencyPropertyOptions.ReadOnly); else if (property != null) isReadOnly = !property.CanWrite; else { Debug.Assert(false); return; } //Deserialize compound properties if (isReadOnly) { object propValue = null; if (dependencyProperty != null && obj is DependencyObject) { if (((DependencyObject)obj).IsBindingSet(dependencyProperty)) propValue = ((DependencyObject)obj).GetBinding(dependencyProperty); else if(!dependencyProperty.IsEvent) propValue = ((DependencyObject)obj).GetValue(dependencyProperty); else propValue = ((DependencyObject)obj).GetHandler(dependencyProperty); } else if (property != null) propValue = property.CanRead ? property.GetValue(obj, null) : null; if (propValue != null) DeserializeContents(serializationManager, propValue, reader); else serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerReadOnlyPropertyAndValueIsNull, propertyName, obj.GetType().FullName), reader)); } else if (!reader.IsEmptyElement) { // if (reader.HasAttributes) { //We allow xmlns on the complex property nodes while (reader.MoveToNextAttribute()) { // if (string.Equals(reader.LocalName, "xmlns", StringComparison.Ordinal) || string.Equals(reader.Prefix, "xmlns", StringComparison.Ordinal)) continue; else serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerAttributesFoundInComplexProperty, propertyName, obj.GetType().FullName), reader)); } } do { if (!reader.Read()) return; } while (reader.NodeType != XmlNodeType.Text && reader.NodeType != XmlNodeType.Element && reader.NodeType != XmlNodeType.ProcessingInstruction && reader.NodeType != XmlNodeType.EndElement); if (reader.NodeType == XmlNodeType.Text) { this.DeserializeSimpleProperty(serializationManager, reader, obj, reader.Value); } else { AdvanceReader(reader); if (reader.NodeType == XmlNodeType.Element) { object propValue = DeserializeObject(serializationManager, reader); if (propValue != null) { propValue = GetValueFromMarkupExtension(serializationManager, propValue); if (propValue != null && propValue.GetType() == typeof(string) && ((string)propValue).StartsWith("{}", StringComparison.Ordinal)) propValue = ((string)propValue).Substring(2); if (dependencyProperty != null) { //Get the serializer for the property type WorkflowMarkupSerializer objSerializer = serializationManager.GetSerializer(obj.GetType(), typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer; if (objSerializer == null) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerNotAvailable, obj.GetType().FullName), reader)); return; } try { objSerializer.SetDependencyPropertyValue(serializationManager, obj, dependencyProperty, propValue); } catch (Exception e) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e, reader)); return; } } else if (property != null) { try { property.SetValue(obj, propValue, null); } catch { serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerComplexPropertySetFailed, new object[] { propertyName, propertyName, obj.GetType().Name }))); } } } } } } } private void DeserializeSimpleProperty(WorkflowMarkupSerializationManager serializationManager, XmlReader reader, object obj, string value) { Type propertyType = null; bool isReadOnly = false; DependencyProperty dependencyProperty = serializationManager.Context.Current as DependencyProperty; PropertyInfo property = serializationManager.Context.Current as PropertyInfo; if (dependencyProperty != null) { propertyType = dependencyProperty.PropertyType; isReadOnly = ((dependencyProperty.DefaultMetadata.Options & DependencyPropertyOptions.ReadOnly) == DependencyPropertyOptions.ReadOnly); } else if (property != null) { propertyType = property.PropertyType; isReadOnly = !property.CanWrite; } else { Debug.Assert(false); return; } if (isReadOnly && !typeof(ICollection ).IsAssignableFrom(propertyType)) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerPrimitivePropertyReadOnly, new object[] { property.Name, property.Name, obj.GetType().FullName }), reader)); return; } DeserializeSimpleMember(serializationManager, propertyType, reader, obj, value); } private void DeserializeEvent(WorkflowMarkupSerializationManager serializationManager, XmlReader reader, object obj, string value) { Type eventType = null; EventInfo evt = serializationManager.Context.Current as EventInfo; DependencyProperty dependencyEvent = serializationManager.Context.Current as DependencyProperty; if (dependencyEvent != null) eventType = dependencyEvent.PropertyType; else if (evt != null) eventType = evt.EventHandlerType; else { Debug.Assert(false); return; } DeserializeSimpleMember(serializationManager, eventType, reader, obj, value); } private void DeserializeSimpleMember(WorkflowMarkupSerializationManager serializationManager, Type memberType, XmlReader reader, object obj, string value) { //Get the serializer for the member type WorkflowMarkupSerializer memberSerializer = serializationManager.GetSerializer(memberType, typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer; if (memberSerializer == null) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerNotAvailable, memberType.FullName), reader)); return; } //Try to deserialize object memberValue = null; try { memberValue = memberSerializer.DeserializeFromString(serializationManager, memberType, value); memberValue = GetValueFromMarkupExtension(serializationManager, memberValue); DependencyProperty dependencyProperty = serializationManager.Context.Current as DependencyProperty; if (dependencyProperty != null) { //Get the serializer for the property type WorkflowMarkupSerializer objSerializer = serializationManager.GetSerializer(obj.GetType(), typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer; if (objSerializer == null) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerNotAvailable, obj.GetType().FullName), reader)); return; } objSerializer.SetDependencyPropertyValue(serializationManager, obj, dependencyProperty, memberValue); } else { EventInfo evt = serializationManager.Context.Current as EventInfo; if (evt != null) { try { WorkflowMarkupSerializationHelpers.SetEventHandlerName(obj, evt.Name, memberValue as string); } catch (Exception e) { while (e is TargetInvocationException && e.InnerException != null) e = e.InnerException; serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerMemberSetFailed, new object[] { reader.LocalName, reader.Value, reader.LocalName, obj.GetType().FullName, e.Message }), e, reader)); } } else { PropertyInfo property = serializationManager.Context.Current as PropertyInfo; if (property != null) { try { if (memberValue is string && TypeProvider.IsAssignable(typeof(Type), property.PropertyType)) { string key = property.ReflectedType.FullName + "." + property.Name; Helpers.SetDesignTimeTypeName(obj, key, memberValue as string); } else if (property.CanWrite) { property.SetValue(obj, memberValue, null); } else if(typeof(ICollection ).IsAssignableFrom(memberValue.GetType())) { ICollection propVal = property.GetValue(obj, null) as ICollection ; ICollection deserializedValue = memberValue as ICollection ; if (propVal != null && deserializedValue != null) { foreach (string content in deserializedValue) propVal.Add(content); } } } catch (Exception e) { while (e is TargetInvocationException && e.InnerException != null) e = e.InnerException; serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerMemberSetFailed, new object[] { reader.LocalName, reader.Value, reader.LocalName, obj.GetType().FullName, e.Message }), e, reader)); } } } } } catch (Exception e) { while (e is TargetInvocationException && e.InnerException != null) e = e.InnerException; serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerMemberSetFailed, new object[] { reader.LocalName, reader.Value, reader.LocalName, obj.GetType().FullName, e.Message }), e, reader)); } } #endregion #region DependencyProperty Support [SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", MessageId="System.String.IndexOf(System.String)", Justification="string comparisons are just used to lookup method/property names from compiled system.type which should not cause any issue irrespective of comparisons mode used")] private DependencyProperty ResolveDependencyProperty(WorkflowMarkupSerializationManager serializationManager, XmlReader reader, object attachedObj, string fullPropertyName) { Type ownerType = null; string propertyName = String.Empty; int separatorIndex = fullPropertyName.IndexOf("."); if (separatorIndex != -1) { string ownerTypeName = fullPropertyName.Substring(0, separatorIndex); propertyName = fullPropertyName.Substring(separatorIndex + 1); if (!String.IsNullOrEmpty(ownerTypeName) && !String.IsNullOrEmpty(propertyName)) ownerType = serializationManager.GetType(new XmlQualifiedName(ownerTypeName, reader.LookupNamespace(reader.Prefix))); } else { ownerType = attachedObj.GetType(); propertyName = fullPropertyName; } if (ownerType == null) return null; //We need to make sure that the register method is always called for the dynamic property before we try to resolve it //In cases of attached properties if this statement is not there then the dynamic property wont be found as it is //not registered till the first access of the static field DependencyProperty dependencyProperty = null; FieldInfo fieldInfo = ownerType.GetField(propertyName + "Property", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); if (fieldInfo == null) fieldInfo = ownerType.GetField(propertyName + "Event", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); if (fieldInfo != null) { dependencyProperty = fieldInfo.GetValue(attachedObj) as DependencyProperty; if (dependencyProperty != null) { object[] attributes = dependencyProperty.DefaultMetadata.GetAttributes(typeof(DesignerSerializationVisibilityAttribute)); if (attributes.Length > 0) { DesignerSerializationVisibilityAttribute serializationVisibilityAttribute = attributes[0] as DesignerSerializationVisibilityAttribute; if (serializationVisibilityAttribute.Visibility == DesignerSerializationVisibility.Hidden) dependencyProperty = null; } } } return dependencyProperty; } #endregion #region SafeXmlNodeWriter private sealed class SafeXmlNodeWriter : IDisposable { private XmlNodeType xmlNodeType = XmlNodeType.None; private WorkflowMarkupSerializationManager serializationManager = null; public SafeXmlNodeWriter(WorkflowMarkupSerializationManager serializationManager, object owner, object property, XmlNodeType xmlNodeType) { this.serializationManager = serializationManager; this.xmlNodeType = xmlNodeType; XmlWriter writer = serializationManager.WorkflowMarkupStack[typeof(XmlWriter)] as XmlWriter; if (writer == null) throw new InvalidOperationException(SR.GetString(SR.Error_InternalSerializerError)); string prefix = String.Empty, tagName = String.Empty, xmlns = String.Empty; DependencyProperty dependencyProperty = property as DependencyProperty; if (dependencyProperty != null) { if (!dependencyProperty.IsAttached && xmlNodeType == XmlNodeType.Attribute) { tagName = dependencyProperty.Name; xmlns = String.Empty; } else { XmlQualifiedName qualifiedName = this.serializationManager.GetXmlQualifiedName(dependencyProperty.OwnerType, out prefix); tagName = qualifiedName.Name + "." + dependencyProperty.Name; xmlns = qualifiedName.Namespace; } } else if (property is MemberInfo) { ExtendedPropertyInfo extendedProperty = property as ExtendedPropertyInfo; if (extendedProperty != null) { XmlQualifiedName qualifiedName = extendedProperty.GetXmlQualifiedName(this.serializationManager, out prefix); tagName = qualifiedName.Name; xmlns = qualifiedName.Namespace; } else if (this.xmlNodeType == XmlNodeType.Element) { XmlQualifiedName qualifiedName = this.serializationManager.GetXmlQualifiedName(owner.GetType(), out prefix); tagName = qualifiedName.Name + "." + ((MemberInfo)property).Name; xmlns = qualifiedName.Namespace; } else { tagName = ((MemberInfo)property).Name; xmlns = String.Empty; } } else { XmlQualifiedName qualifiedName = this.serializationManager.GetXmlQualifiedName(owner.GetType(), out prefix); tagName = qualifiedName.Name; xmlns = qualifiedName.Namespace; } //verify the node name is valid. This may happen for design time names as // "(Parameter) PropName" tagName = XmlConvert.EncodeName(tagName); if (this.xmlNodeType == XmlNodeType.Element) { writer.WriteStartElement(prefix, tagName, xmlns); this.serializationManager.WriterDepth += 1; } else if (this.xmlNodeType == XmlNodeType.Attribute) { writer.WriteStartAttribute(prefix, tagName, xmlns); } } #region IDisposable Members void IDisposable.Dispose() { XmlWriter writer = this.serializationManager.WorkflowMarkupStack[typeof(XmlWriter)] as XmlWriter; if (writer != null && writer.WriteState != WriteState.Error) { if (this.xmlNodeType == XmlNodeType.Element) { writer.WriteEndElement(); this.serializationManager.WriterDepth -= 1; } else if (writer.WriteState == WriteState.Attribute) { writer.WriteEndAttribute(); } } } #endregion } #endregion #region Property Info Lookup private static PropertyInfo LookupProperty(IList properties, string propertyName) { if (properties != null && !string.IsNullOrEmpty(propertyName)) { foreach (PropertyInfo property in properties) { if (property.Name == propertyName) return property; } } return null; } private static EventInfo LookupEvent(IList events, string eventName) { if (events != null && !string.IsNullOrEmpty(eventName)) { foreach (EventInfo evt in events) { if (evt.Name == eventName) return evt; } } return null; } #endregion #endregion #region Compact Attribute Support internal bool IsValidCompactAttributeFormat(string attributeValue) { return (attributeValue.Length > 0 && attributeValue.StartsWith("{", StringComparison.Ordinal) && !attributeValue.StartsWith("{}", StringComparison.Ordinal) && attributeValue.EndsWith("}", StringComparison.Ordinal)); } // This function parses the data bind syntax (markup extension in xaml terms). The syntax is: // {ObjectTypeName arg1, arg2, name3=arg3, name4=arg4, ...} // For example, an ActivityBind would have the syntax as the following: // {wcm:ActivityBind ID=Workflow1, Path=error1} // We also support positional arguments, so the above expression is equivalent to // {wcm:ActivityBind Workflow1, Path=error1} or {wcm:ActivityBind Workflow1, error1} // Notice that the object must have the appropriate constructor to support positional arugments. // There should be no constructors that takes the same number of arugments, regardless of their types. internal object DeserializeFromCompactFormat(WorkflowMarkupSerializationManager serializationManager, XmlReader reader, string attrValue) { if (attrValue.Length == 0 || !attrValue.StartsWith("{", StringComparison.Ordinal) || !attrValue.EndsWith("}", StringComparison.Ordinal)) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.IncorrectSyntax, attrValue), reader)); return null; } // check for correct format: typename name=value name=value int argIndex = attrValue.IndexOf(" ", StringComparison.Ordinal); if (argIndex == -1) argIndex = attrValue.IndexOf("}", StringComparison.Ordinal); string typename = attrValue.Substring(1, argIndex-1).Trim(); string arguments = attrValue.Substring(argIndex + 1, attrValue.Length - (argIndex + 1)); // lookup the type of the target string prefix = String.Empty; int typeIndex = typename.IndexOf(":", StringComparison.Ordinal); if (typeIndex >= 0) { prefix = typename.Substring(0, typeIndex); typename = typename.Substring(typeIndex + 1); } Type type = serializationManager.GetType(new XmlQualifiedName(typename, reader.LookupNamespace(prefix))); if (type == null && !typename.EndsWith("Extension", StringComparison.Ordinal)) { typename = typename + "Extension"; type = serializationManager.GetType(new XmlQualifiedName(typename , reader.LookupNamespace(prefix))); } if(type == null) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_MarkupSerializerTypeNotResolved, typename), reader)); return null; } // Break apart the argument string. object obj = null; Dictionary namedArgs = new Dictionary (); ArrayList argTokens = null; try { argTokens = TokenizeAttributes(serializationManager, arguments, (reader is IXmlLineInfo) ? ((IXmlLineInfo)reader).LineNumber : 1, (reader is IXmlLineInfo) ? ((IXmlLineInfo)reader).LinePosition : 1); } catch(Exception error) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_MarkupExtensionDeserializeFailed, attrValue, error.Message), reader)); return null; } if (argTokens != null) { // Process the positional arugments and find the correct constructor to call. ArrayList positionalArgs = new ArrayList(); bool firstEqual = true; for (int i = 0; i < argTokens.Count; i++) { char token = (argTokens[i] is char) ? (char)argTokens[i] : '\0'; if (token == '=') { if (positionalArgs.Count > 0 && firstEqual) positionalArgs.RemoveAt(positionalArgs.Count - 1); firstEqual = false; namedArgs.Add(argTokens[i - 1] as string, argTokens[i + 1] as string); i++; } if (token == ',') continue; if (namedArgs.Count == 0) positionalArgs.Add(argTokens[i] as string); } if (positionalArgs.Count > 0) { ConstructorInfo matchConstructor = null; ConstructorInfo[] constructors = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); ParameterInfo[] matchParameters = null; foreach (ConstructorInfo ctor in constructors) { ParameterInfo[] parameters = ctor.GetParameters(); if (parameters.Length == positionalArgs.Count) { matchConstructor = ctor; matchParameters = parameters; break; } } if (matchConstructor != null) { for (int i = 0; i < positionalArgs.Count; i++) { positionalArgs[i] = XmlConvert.DecodeName((string)positionalArgs[i]); string argVal = (string)positionalArgs[i]; RemoveEscapes(ref argVal); positionalArgs[i] = InternalDeserializeFromString(serializationManager, matchParameters[i].ParameterType, argVal); positionalArgs[i] = GetValueFromMarkupExtension(serializationManager, positionalArgs[i]); } obj = Activator.CreateInstance(type, positionalArgs.ToArray()); } } else obj = Activator.CreateInstance(type); } else obj = Activator.CreateInstance(type); if (obj == null) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_CantCreateInstanceOfBaseType, type.FullName), reader)); return null; } if (namedArgs.Count > 0) { WorkflowMarkupSerializer serializer = serializationManager.GetSerializer(obj.GetType(), typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer; if (serializer == null) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerNotAvailable, obj.GetType().FullName), reader)); return obj; } List properties = new List (); try { properties.AddRange(serializer.GetProperties(serializationManager, obj)); properties.AddRange(serializationManager.GetExtendedProperties(obj)); } catch (Exception e) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e, reader)); return obj; } foreach (string key in namedArgs.Keys) { string argName = key; string argVal = namedArgs[key] as string; RemoveEscapes(ref argName); RemoveEscapes(ref argVal); PropertyInfo property = WorkflowMarkupSerializer.LookupProperty(properties, argName); if (property != null) { serializationManager.Context.Push(property); try { DeserializeSimpleProperty(serializationManager, reader, obj, argVal); } finally { Debug.Assert((PropertyInfo)serializationManager.Context.Current == property, "Serializer did not remove an object it pushed into stack."); serializationManager.Context.Pop(); } } else { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerPrimitivePropertyNoLogic, new object[] { argName, argName, obj.GetType().FullName }), reader)); } } } return obj; } // This function splits the argument string into an array of tokens. // For example: ID=Workflow1, Path=error1} would become an array that contains the following elements // {ID} {=} {Workflwo1} {,} {Path} {=} {error1} // Note that the input string should start with the first argument and end with '}'. private ArrayList TokenizeAttributes(WorkflowMarkupSerializationManager serializationManager, string args, int lineNumber, int linePosition) { ArrayList list = null; int length = args.Length; bool inQuotes = false; bool gotEscape = false; bool nonWhitespaceFound = false; Char quoteChar = '\''; int leftCurlies = 0; bool collectionIndexer = false; StringBuilder stringBuilder = null; int i = 0; // Loop through the args, creating a list of arguments and known delimiters. // This loop does limited syntax checking, and serves to tokenize the argument // string into chunks that are validated in greater detail in the next phase. for (; i < length; i++) { // Escape character is always in effect for everything inside // a MarkupExtension. We have to remember that the next character is // escaped, and is not treated as a quote or delimiter. if (!gotEscape && args[i] == '\\') { gotEscape = true; continue; } if (!nonWhitespaceFound && !Char.IsWhiteSpace(args[i])) { nonWhitespaceFound = true; } // Process all characters that are not whitespace or are between quotes if (inQuotes || leftCurlies > 0 || nonWhitespaceFound) { // We have a non-whitespace character, so ensure we have // a string builder to accumulate characters and a list to collect // attributes and delimiters. These are lazily // created so that simple cases that have no parameters do not // create any extra objects. if (stringBuilder == null) { stringBuilder = new StringBuilder(length); list = new ArrayList(1); } // If the character is escaped, then it is part of the attribute // being collected, regardless of its value and is not treated as // a delimiter or special character. Write back the escape // character since downstream processing will need it to determine // whether the value is a MarkupExtension or not, and to prevent // multiple escapes from being lost by recursive processing. if (gotEscape) { stringBuilder.Append('\\'); stringBuilder.Append(args[i]); gotEscape = false; continue; } // If this characters is not escaped, then look for quotes and // delimiters. if (inQuotes || leftCurlies > 0) { if (inQuotes && args[i] == quoteChar) { // If we're inside quotes, then only an end quote that is not // escaped is special, and will act as a delimiter. inQuotes = false; list.Add(stringBuilder.ToString()); stringBuilder.Length = 0; nonWhitespaceFound = false; } else { if (leftCurlies > 0 && args[i] == '}') { leftCurlies--; } else if (args[i] == '{') { leftCurlies++; } stringBuilder.Append(args[i]); } } else { if (args[i] == '"' || args[i] == '\'') { // If we're not inside quotes, then a start quote can only // occur as the first non-whitespace character in a name or value. if (collectionIndexer && i < args.Length - 1 && args[i + 1] == ']') { collectionIndexer = false; stringBuilder.Append(args[i]); } else if (i > 0 && args[i - 1] == '[') { collectionIndexer = true; stringBuilder.Append(args[i]); } else { if (stringBuilder.Length != 0) return null; inQuotes = true; quoteChar = args[i]; } } else if (args[i] == ',' || args[i] == '=') { // If there is something in the stringbuilder, then store it if (stringBuilder != null && stringBuilder.Length > 0) { list.Add(stringBuilder.ToString().Trim()); stringBuilder.Length = 0; } else if (list.Count == 0 || list[list.Count - 1] is Char) { // Can't have two delimiters in a row, so check what is on // the list and complain if the last item is a character, or if // a delimiter is the first item. return null; } // Append known delimiters. list.Add(args[i]); nonWhitespaceFound = false; } else if (args[i] == '}') { // If we hit the outside right curly brace, then end processing. If // there is a delimiter on the top of the stack and we haven't // hit another non-whitespace character, then its an error if (stringBuilder != null) { if (stringBuilder.Length > 0) { list.Add(stringBuilder.ToString().Trim()); stringBuilder.Length = 0; } else if (list.Count > 0 && (list[list.Count - 1] is Char)) return null; } break; } else { if (args[i] == '{') { leftCurlies++; } // Must just be a plain old character, so add it to the stringbuilder stringBuilder.Append(args[i]); } } } } // If we've accumulated content but haven't hit a terminating '}' then the // format is bad, so complain. if (stringBuilder != null && stringBuilder.Length > 0) throw new Exception(SR.GetString(SR.Error_MarkupExtensionMissingTerminatingCharacter)); else if (i < length) { // If there is non-whitespace text left that we haven't processes yet, // then there is junk after the closing '}', so complain for (i = i + 1; i < length; i++) { if (!Char.IsWhiteSpace(args[i])) throw new Exception(SR.GetString(SR.Error_ExtraCharacterFoundAtEnd)); } } return list; } // Remove any '\' escape characters from the passed string. This does a simple // pass through the string and won't do anything if there are no '\' characters. private void RemoveEscapes(ref string value) { StringBuilder builder = null; bool noEscape = true; for (int i = 0; i < value.Length; i++) { if (noEscape && value[i] == '\\') { if (builder == null) { builder = new StringBuilder(value.Length); builder.Append(value.Substring(0, i)); } noEscape = false; } else if (builder != null) { builder.Append(value[i]); noEscape = true; } } if (builder != null) { value = builder.ToString(); } } #endregion #region ContentProperty Support private class ContentProperty : IDisposable { private WorkflowMarkupSerializationManager serializationManager; private WorkflowMarkupSerializer parentObjectSerializer; private object parentObject; private PropertyInfo contentProperty; private WorkflowMarkupSerializer contentPropertySerializer; public ContentProperty(WorkflowMarkupSerializationManager serializationManager, WorkflowMarkupSerializer parentObjectSerializer, object parentObject) { this.serializationManager = serializationManager; this.parentObjectSerializer = parentObjectSerializer; this.parentObject = parentObject; this.contentProperty = GetContentProperty(this.serializationManager, this.parentObject); if (this.contentProperty != null) { this.contentPropertySerializer = this.serializationManager.GetSerializer(this.contentProperty.PropertyType, typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer; if (this.contentPropertySerializer != null) { try { XmlReader reader = this.serializationManager.WorkflowMarkupStack[typeof(XmlReader)] as XmlReader; object contentPropertyValue = null; if (reader == null) { contentPropertyValue = this.contentProperty.GetValue(this.parentObject, null); } else if (!this.contentProperty.PropertyType.IsValueType && !this.contentProperty.PropertyType.IsPrimitive && this.contentProperty.PropertyType != typeof(string) && !IsMarkupExtension(this.contentProperty.PropertyType) && this.contentProperty.CanWrite) { WorkflowMarkupSerializer serializer = serializationManager.GetSerializer(this.contentProperty.PropertyType, typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer; if (serializer == null) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerNotAvailable, this.contentProperty.PropertyType.FullName), reader)); return; } try { contentPropertyValue = serializer.CreateInstance(serializationManager, this.contentProperty.PropertyType); } catch (Exception e) { serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerCreateInstanceFailed, this.contentProperty.PropertyType.FullName, e.Message), reader)); return; } this.contentProperty.SetValue(this.parentObject, contentPropertyValue, null); } if (contentPropertyValue != null) { if (reader != null) { this.contentPropertySerializer.OnBeforeDeserialize(this.serializationManager, contentPropertyValue); this.contentPropertySerializer.OnBeforeDeserializeContents(this.serializationManager, contentPropertyValue); } } } catch (Exception e) { this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, this.parentObject.GetType(), e.Message), e)); } } else { this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerNotAvailableForSerialize, this.contentProperty.PropertyType.FullName))); } } } void IDisposable.Dispose() { XmlReader reader = this.serializationManager.WorkflowMarkupStack[typeof(XmlReader)] as XmlReader; if (reader != null && this.contentProperty != null && this.contentPropertySerializer != null) { try { object contentPropertyValue = this.contentProperty.GetValue(this.parentObject, null); if (contentPropertyValue != null) this.contentPropertySerializer.OnAfterDeserialize(this.serializationManager, contentPropertyValue); } catch (Exception e) { this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, this.parentObject.GetType(), e.Message), e)); } } } internal PropertyInfo Property { get { return this.contentProperty; } } internal object GetContents() { object value = null; if (this.contentProperty != null) value = this.contentProperty.GetValue(this.parentObject, null); else value = this.parentObjectSerializer.GetChildren(this.serializationManager, this.parentObject); return value; } internal void SetContents(IList contents) { if (contents.Count == 0) return; if (this.contentProperty == null) { int i = 0; try { foreach (ContentInfo contentInfo in contents) { this.parentObjectSerializer.AddChild(this.serializationManager, this.parentObject, contentInfo.Content); i += 1; } } catch (Exception e) { this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, this.parentObject.GetType(), e.Message), e, contents[i].LineNumber, contents[i].LinePosition)); } } else if (this.contentPropertySerializer != null) { object propertyValue = this.contentProperty.GetValue(this.parentObject, null); if (CollectionMarkupSerializer.IsValidCollectionType(this.contentProperty.PropertyType)) { if (propertyValue == null) { this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_ContentPropertyCanNotBeNull, this.contentProperty.Name, this.parentObject.GetType().FullName))); return; } //Notify serializer about begining of deserialization process int i = 0; try { foreach (ContentInfo contentInfo in contents) { this.contentPropertySerializer.AddChild(this.serializationManager, propertyValue, contentInfo.Content); i = i + 1; } } catch (Exception e) { this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, this.parentObject.GetType(), e.Message), e, contents[i].LineNumber, contents[i].LinePosition)); } } else { if (!this.contentProperty.CanWrite) { this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_ContentPropertyNoSetter, this.contentProperty.Name, this.parentObject.GetType()), contents[0].LineNumber, contents[0].LinePosition)); return; } if (contents.Count > 1) this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_ContentPropertyNoMultipleContents, this.contentProperty.Name, this.parentObject.GetType()), contents[1].LineNumber, contents[1].LinePosition)); object content = contents[0].Content; if (!this.contentProperty.PropertyType.IsAssignableFrom(content.GetType()) && typeof(string).IsAssignableFrom(content.GetType())) { try { content = this.contentPropertySerializer.DeserializeFromString(this.serializationManager, this.contentProperty.PropertyType, content as string); content = WorkflowMarkupSerializer.GetValueFromMarkupExtension(this.serializationManager, content); } catch (Exception e) { this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, this.parentObject.GetType(), e.Message), e, contents[0].LineNumber, contents[0].LinePosition)); return; } } if (content == null) { this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_ContentCanNotBeConverted, content as string, contentProperty.Name, this.parentObject.GetType().FullName, this.contentProperty.PropertyType.FullName), contents[0].LineNumber, contents[0].LinePosition)); } else if (!contentProperty.PropertyType.IsAssignableFrom(content.GetType())) { this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_ContentPropertyValueInvalid, content.GetType(), this.contentProperty.Name, this.contentProperty.PropertyType.FullName), contents[0].LineNumber, contents[0].LinePosition)); } else { try { if (this.contentProperty.PropertyType == typeof(string)) { content = new WorkflowMarkupSerializer().DeserializeFromString(this.serializationManager, this.contentProperty.PropertyType, content as string); content = WorkflowMarkupSerializer.GetValueFromMarkupExtension(this.serializationManager, content); } this.contentProperty.SetValue(this.parentObject, content, null); } catch (Exception e) { this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, this.parentObject.GetType(), e.Message), e, contents[0].LineNumber, contents[0].LinePosition)); } } } } } private PropertyInfo GetContentProperty(WorkflowMarkupSerializationManager serializationManager, object parentObject) { PropertyInfo contentProperty = null; string contentPropertyName = String.Empty; object[] contentPropertyAttributes = parentObject.GetType().GetCustomAttributes(typeof(ContentPropertyAttribute), true); if (contentPropertyAttributes != null && contentPropertyAttributes.Length > 0) contentPropertyName = ((ContentPropertyAttribute)contentPropertyAttributes[0]).Name; if (!String.IsNullOrEmpty(contentPropertyName)) { contentProperty = parentObject.GetType().GetProperty(contentPropertyName, BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.Public); if (contentProperty == null) serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_ContentPropertyCouldNotBeFound, contentPropertyName, parentObject.GetType().FullName))); } return contentProperty; } } private struct ContentInfo { public int LineNumber; public int LinePosition; public object Content; public ContentInfo(object content, int lineNumber, int linePosition) { this.Content = content; this.LineNumber = lineNumber; this.LinePosition = linePosition; } } #endregion #region MarkupExtension Support internal static string EnsureMarkupExtensionTypeName(Type type) { string extensionName = type.Name; if (extensionName.EndsWith(StandardXomlKeys.MarkupExtensionSuffix, StringComparison.OrdinalIgnoreCase)) extensionName = extensionName.Substring(0, extensionName.Length - StandardXomlKeys.MarkupExtensionSuffix.Length); return extensionName; } internal static string EnsureMarkupExtensionTypeName(XmlQualifiedName xmlQualifiedName) { string typeName = xmlQualifiedName.Name; if (xmlQualifiedName.Namespace.Equals(StandardXomlKeys.Definitions_XmlNs, StringComparison.Ordinal)) { if (typeName.Equals(typeof(Array).Name, StringComparison.Ordinal)) typeName = typeof(ArrayExtension).Name; } return typeName; } private static bool IsMarkupExtension(Type type) { return (typeof(MarkupExtension).IsAssignableFrom(type) || typeof(System.Type).IsAssignableFrom(type) || typeof(System.Array).IsAssignableFrom(type)); } private static bool IsMarkupExtension(XmlQualifiedName xmlQualifiedName) { bool markupExtension = false; if (xmlQualifiedName.Namespace.Equals(StandardXomlKeys.Definitions_XmlNs, StringComparison.Ordinal)) { if (xmlQualifiedName.Name.Equals(typeof(Array).Name) || string.Equals(xmlQualifiedName.Name, "Null", StringComparison.Ordinal) || string.Equals(xmlQualifiedName.Name, typeof(NullExtension).Name, StringComparison.Ordinal) || string.Equals(xmlQualifiedName.Name, "Type", StringComparison.Ordinal) || string.Equals(xmlQualifiedName.Name, typeof(TypeExtension).Name, StringComparison.Ordinal)) markupExtension = true; } return markupExtension; } private static object GetMarkupExtensionFromValue(object value) { if (value == null) return new NullExtension(); if (value is System.Type) return new TypeExtension(value as System.Type); if(value is Array) return new ArrayExtension(value as Array); return value; } private static object GetValueFromMarkupExtension(WorkflowMarkupSerializationManager manager, object extension) { object value = extension; MarkupExtension markupExtension = extension as MarkupExtension; if (markupExtension != null) value = markupExtension.ProvideValue(manager); return value; } #endregion } #endregion } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- InProcStateClientManager.cs
- TextServicesDisplayAttribute.cs
- MetadataSerializer.cs
- PartialArray.cs
- EvidenceTypeDescriptor.cs
- Cursor.cs
- CodeGotoStatement.cs
- MenuBindingsEditor.cs
- JsonClassDataContract.cs
- EncryptedPackage.cs
- IPCCacheManager.cs
- ApplicationHost.cs
- DBConnection.cs
- XmlLangPropertyAttribute.cs
- ScaleTransform.cs
- TabControlToolboxItem.cs
- ProtocolsConfigurationHandler.cs
- AllowedAudienceUriElement.cs
- AppModelKnownContentFactory.cs
- PropertyPathWorker.cs
- ContentFileHelper.cs
- _ScatterGatherBuffers.cs
- COSERVERINFO.cs
- SapiAttributeParser.cs
- FontUnit.cs
- CopyEncoder.cs
- HttpCapabilitiesBase.cs
- Serialization.cs
- DataPointer.cs
- CompressStream.cs
- HostVisual.cs
- DesigntimeLicenseContext.cs
- ColumnResizeAdorner.cs
- AsyncResult.cs
- BigInt.cs
- FlowDocumentReaderAutomationPeer.cs
- TraceLevelStore.cs
- TextBox.cs
- XmlQualifiedNameTest.cs
- HtmlTextViewAdapter.cs
- TypedOperationInfo.cs
- SingleKeyFrameCollection.cs
- HttpCachePolicyBase.cs
- HtmlUtf8RawTextWriter.cs
- DependencyObjectType.cs
- WebSysDefaultValueAttribute.cs
- Helpers.cs
- ReferenceService.cs
- Timer.cs
- TextContainer.cs
- WebServiceEnumData.cs
- PackageRelationshipCollection.cs
- _UriSyntax.cs
- GenericWebPart.cs
- WebBrowserNavigatingEventHandler.cs
- SafeNativeMethodsMilCoreApi.cs
- XmlAutoDetectWriter.cs
- PageEventArgs.cs
- DrawingVisualDrawingContext.cs
- ErrorProvider.cs
- Marshal.cs
- InvokeGenerator.cs
- LinkTarget.cs
- SQLMembershipProvider.cs
- HttpCookiesSection.cs
- WCFBuildProvider.cs
- PageSetupDialog.cs
- UriGenerator.cs
- InfiniteIntConverter.cs
- PartitionResolver.cs
- ClientTargetCollection.cs
- ScrollProviderWrapper.cs
- EntitySetBaseCollection.cs
- CfgParser.cs
- GridViewRowEventArgs.cs
- ImageMapEventArgs.cs
- HtmlInputHidden.cs
- UrlParameterReader.cs
- HierarchicalDataBoundControl.cs
- DataControlFieldHeaderCell.cs
- HistoryEventArgs.cs
- CapabilitiesUse.cs
- ResizeBehavior.cs
- ExceptionRoutedEventArgs.cs
- TableRowGroup.cs
- MetafileHeaderWmf.cs
- BaseCodeDomTreeGenerator.cs
- DataGridViewElement.cs
- SemanticResultKey.cs
- DataTableNewRowEvent.cs
- WebSysDefaultValueAttribute.cs
- Debug.cs
- SocketConnection.cs
- DoneReceivingAsyncResult.cs
- BaseValidatorDesigner.cs
- MouseDevice.cs
- D3DImage.cs
- BuildProvider.cs
- BaseResourcesBuildProvider.cs
- CatalogZoneBase.cs