e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
232 lines
14 KiB
C#
232 lines
14 KiB
C#
namespace System.Workflow.ComponentModel.Serialization
|
|
{
|
|
using System;
|
|
using System.CodeDom;
|
|
using System.ComponentModel;
|
|
using System.ComponentModel.Design;
|
|
using System.ComponentModel.Design.Serialization;
|
|
using System.Collections;
|
|
using System.Resources;
|
|
using System.Workflow.ComponentModel.Design;
|
|
using System.Collections.Generic;
|
|
using Microsoft.CSharp;
|
|
using System.Workflow.ComponentModel;
|
|
using System.Workflow.ComponentModel.Compiler;
|
|
using System.CodeDom.Compiler;
|
|
using System.IO;
|
|
using System.Reflection;
|
|
using System.Diagnostics;
|
|
|
|
#region Class DependencyObjectCodeDomSerializer
|
|
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
|
|
public class DependencyObjectCodeDomSerializer : CodeDomSerializer
|
|
{
|
|
public DependencyObjectCodeDomSerializer()
|
|
{
|
|
}
|
|
|
|
public override object Serialize(IDesignerSerializationManager manager, object obj)
|
|
{
|
|
if (manager == null)
|
|
throw new ArgumentNullException("manager");
|
|
|
|
if (manager.Context == null)
|
|
throw new ArgumentException("manager", SR.GetString(SR.Error_MissingContextProperty));
|
|
|
|
if (obj == null)
|
|
throw new ArgumentNullException("obj");
|
|
|
|
DependencyObject dependencyObject = obj as DependencyObject;
|
|
if (dependencyObject == null)
|
|
throw new ArgumentException(SR.GetString(SR.Error_UnexpectedArgumentType, typeof(DependencyObject).FullName), "obj");
|
|
|
|
Activity activity = obj as Activity;
|
|
if (activity != null)
|
|
manager.Context.Push(activity);
|
|
|
|
CodeStatementCollection retVal = null;
|
|
try
|
|
{
|
|
if (activity != null)
|
|
{
|
|
CodeDomSerializer componentSerializer = manager.GetSerializer(typeof(Component), typeof(CodeDomSerializer)) as CodeDomSerializer;
|
|
if (componentSerializer == null)
|
|
throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(CodeDomSerializer).FullName));
|
|
retVal = componentSerializer.Serialize(manager, activity) as CodeStatementCollection;
|
|
}
|
|
else
|
|
{
|
|
retVal = base.Serialize(manager, obj) as CodeStatementCollection;
|
|
}
|
|
|
|
if (retVal != null)
|
|
{
|
|
CodeStatementCollection codeStatements = new CodeStatementCollection(retVal);
|
|
CodeExpression objectExpression = SerializeToExpression(manager, obj);
|
|
if (objectExpression != null)
|
|
{
|
|
ArrayList propertiesSerialized = new ArrayList();
|
|
List<DependencyProperty> dependencyProperties = new List<DependencyProperty>(dependencyObject.MetaDependencyProperties);
|
|
foreach (DependencyProperty dp in dependencyObject.DependencyPropertyValues.Keys)
|
|
{
|
|
if (dp.IsAttached)
|
|
{
|
|
if ((dp.IsEvent && dp.OwnerType.GetField(dp.Name + "Event", BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly) != null) ||
|
|
(!dp.IsEvent && dp.OwnerType.GetField(dp.Name + "Property", BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly) != null))
|
|
dependencyProperties.Add(dp);
|
|
}
|
|
}
|
|
foreach (DependencyProperty dependencyProperty in dependencyProperties)
|
|
{
|
|
object value = null;
|
|
if (dependencyObject.IsBindingSet(dependencyProperty))
|
|
value = dependencyObject.GetBinding(dependencyProperty);
|
|
else if (!dependencyProperty.IsEvent)
|
|
value = dependencyObject.GetValue(dependencyProperty);
|
|
else
|
|
value = dependencyObject.GetHandler(dependencyProperty);
|
|
// Attached property should always be set through SetValue, no matter if it's a meta property or if there is a data context.
|
|
// Other meta properties will be directly assigned.
|
|
// Other instance property will go through SetValue if there is a data context or if it's of type Bind.
|
|
if (value != null &&
|
|
(dependencyProperty.IsAttached || (!dependencyProperty.DefaultMetadata.IsMetaProperty && value is ActivityBind)))
|
|
{
|
|
object[] attributes = dependencyProperty.DefaultMetadata.GetAttributes(typeof(DesignerSerializationVisibilityAttribute));
|
|
if (attributes.Length > 0)
|
|
{
|
|
DesignerSerializationVisibilityAttribute serializationVisibilityAttribute = attributes[0] as DesignerSerializationVisibilityAttribute;
|
|
if (serializationVisibilityAttribute.Visibility == DesignerSerializationVisibility.Hidden)
|
|
continue;
|
|
}
|
|
|
|
// Events of type Bind will go through here. Regular events will go through IEventBindingService.
|
|
CodeExpression param1 = null;
|
|
string dependencyPropertyName = dependencyProperty.Name + ((dependencyProperty.IsEvent) ? "Event" : "Property");
|
|
FieldInfo fieldInfo = dependencyProperty.OwnerType.GetField(dependencyPropertyName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
|
|
if (fieldInfo != null && !fieldInfo.IsPublic)
|
|
param1 = new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(typeof(DependencyProperty)), "FromName", new CodePrimitiveExpression(dependencyProperty.Name), new CodeTypeOfExpression(dependencyProperty.OwnerType));
|
|
else
|
|
param1 = new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(dependencyProperty.OwnerType), dependencyPropertyName);
|
|
|
|
CodeExpression param2 = SerializeToExpression(manager, value);
|
|
|
|
//Fields property fails to serialize to expression due to reference not being created,
|
|
//the actual code for fields are generated in datacontext code generator so we do nothing here
|
|
if (param1 != null && param2 != null)
|
|
{
|
|
CodeMethodInvokeExpression codeMethodInvokeExpr = null;
|
|
if (value is ActivityBind)
|
|
codeMethodInvokeExpr = new CodeMethodInvokeExpression(objectExpression, "SetBinding", new CodeExpression[] { param1, new CodeCastExpression(new CodeTypeReference(typeof(ActivityBind)), param2) });
|
|
else
|
|
codeMethodInvokeExpr = new CodeMethodInvokeExpression(objectExpression, (dependencyProperty.IsEvent) ? "AddHandler" : "SetValue", new CodeExpression[] { param1, param2 });
|
|
retVal.Add(codeMethodInvokeExpr);
|
|
|
|
// Remove the property set statement for the event which is replaced by the SetValue() expression.
|
|
foreach (CodeStatement statement in codeStatements)
|
|
{
|
|
if (statement is CodeAssignStatement && ((CodeAssignStatement)statement).Left is CodePropertyReferenceExpression)
|
|
{
|
|
CodePropertyReferenceExpression prop = ((CodeAssignStatement)statement).Left as CodePropertyReferenceExpression;
|
|
if (prop.PropertyName == dependencyProperty.Name && prop.TargetObject.Equals(objectExpression))
|
|
retVal.Remove(statement);
|
|
}
|
|
}
|
|
}
|
|
|
|
propertiesSerialized.Add(dependencyProperty);
|
|
}
|
|
}
|
|
|
|
IEventBindingService eventBindingService = manager.GetService(typeof(IEventBindingService)) as IEventBindingService;
|
|
if (eventBindingService == null)
|
|
{
|
|
// At compile time, we don't have an event binding service. We need to mannually emit the code to add
|
|
// event handlers.
|
|
foreach (EventDescriptor eventDesc in TypeDescriptor.GetEvents(dependencyObject))
|
|
{
|
|
string handler = WorkflowMarkupSerializationHelpers.GetEventHandlerName(dependencyObject, eventDesc.Name);
|
|
if (!string.IsNullOrEmpty(handler))
|
|
{
|
|
CodeEventReferenceExpression eventRef = new CodeEventReferenceExpression(objectExpression, eventDesc.Name);
|
|
CodeDelegateCreateExpression listener = new CodeDelegateCreateExpression(new CodeTypeReference(eventDesc.EventType), new CodeThisReferenceExpression(), handler);
|
|
retVal.Add(new CodeAttachEventStatement(eventRef, listener));
|
|
}
|
|
}
|
|
}
|
|
|
|
// We also need to handle properties of type System.Type. If the value is a design time type, xomlserializer
|
|
// is not going to be able to deserialize the type. We then store the type name in the user data and
|
|
// output a "typeof(xxx)" expression using the type name w/o validating the type.
|
|
if (dependencyObject.UserData.Contains(UserDataKeys.DesignTimeTypeNames))
|
|
{
|
|
Hashtable typeNames = dependencyObject.UserData[UserDataKeys.DesignTimeTypeNames] as Hashtable;
|
|
foreach (object key in typeNames.Keys)
|
|
{
|
|
string propName = null;
|
|
string ownerTypeName = null;
|
|
string typeName = typeNames[key] as string;
|
|
DependencyProperty dependencyProperty = key as DependencyProperty;
|
|
if (dependencyProperty != null)
|
|
{
|
|
if (propertiesSerialized.Contains(dependencyProperty))
|
|
continue;
|
|
|
|
object[] attributes = dependencyProperty.DefaultMetadata.GetAttributes(typeof(DesignerSerializationVisibilityAttribute));
|
|
if (attributes.Length > 0)
|
|
{
|
|
DesignerSerializationVisibilityAttribute serializationVisibilityAttribute = attributes[0] as DesignerSerializationVisibilityAttribute;
|
|
if (serializationVisibilityAttribute.Visibility == DesignerSerializationVisibility.Hidden)
|
|
continue;
|
|
}
|
|
|
|
propName = dependencyProperty.Name;
|
|
ownerTypeName = dependencyProperty.OwnerType.FullName;
|
|
}
|
|
else if (key is string)
|
|
{
|
|
int indexOfDot = ((string)key).LastIndexOf('.');
|
|
Debug.Assert(indexOfDot != -1, "Wrong property name in DesignTimeTypeNames hashtable.");
|
|
if (indexOfDot != -1)
|
|
{
|
|
ownerTypeName = ((string)key).Substring(0, indexOfDot);
|
|
propName = ((string)key).Substring(indexOfDot + 1);
|
|
}
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(typeName) && !string.IsNullOrEmpty(propName) && !string.IsNullOrEmpty(ownerTypeName))
|
|
{
|
|
if (ownerTypeName == obj.GetType().FullName)
|
|
{
|
|
// Property is not an attached property. Serialize using regular property set expression.
|
|
CodePropertyReferenceExpression propertyRef = new CodePropertyReferenceExpression(objectExpression, propName);
|
|
retVal.Add(new CodeAssignStatement(propertyRef, new CodeTypeOfExpression(typeName)));
|
|
}
|
|
else
|
|
{
|
|
// This is an attached property. Serialize using SetValue() expression.
|
|
CodeExpression param1 = new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(ownerTypeName), propName + "Property");
|
|
CodeExpression param2 = new CodeTypeOfExpression(typeName);
|
|
retVal.Add(new CodeMethodInvokeExpression(objectExpression, "SetValue", new CodeExpression[] { param1, param2 }));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if (activity != null)
|
|
{
|
|
object pushedActivity = manager.Context.Pop();
|
|
System.Diagnostics.Debug.Assert(pushedActivity == activity);
|
|
}
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
}
|