//
// System.ComponentModel.Design.Serialization.CodeDomSerializerBase
//
// Authors:
// Ivan N. Zlatev (contact i-nZ.net)
//
// (C) 2007 Ivan N. Zlatev
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#if NET_2_0
using System;
using System.Collections;
using System.Reflection;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.CodeDom;
namespace System.ComponentModel.Design.Serialization{
[EditorBrowsable (EditorBrowsableState.Never)]
public abstract class CodeDomSerializerBase
{
// MSDN says that if the deserialization fails a CodeExpression is returned
//
private sealed class DeserializationErrorMarker : CodeExpression
{
public override bool Equals (object o)
{
return false;
}
public override int GetHashCode ()
{
return base.GetHashCode ();
}
}
private static readonly DeserializationErrorMarker _errorMarker = new DeserializationErrorMarker ();
internal CodeDomSerializerBase ()
{
}
private class ExpressionTable : Hashtable // just so that we have a specific type to append to the context stack
{
}
protected CodeExpression SerializeToExpression (IDesignerSerializationManager manager, object instance)
{
if (manager == null)
throw new ArgumentNullException ("manager");
CodeExpression expression = null;
if (instance != null)
expression = this.GetExpression (manager, instance); // 1 - IDesignerSerializationManager.GetExpression
if (expression == null) {
CodeDomSerializer serializer = this.GetSerializer (manager, instance); // 2 - manager.GetSerializer().Serialize()
if (serializer != null) {
object serialized = serializer.Serialize (manager, instance);
expression = serialized as CodeExpression; // 3 - CodeStatement or CodeStatementCollection
if (expression == null) {
CodeStatement statement = serialized as CodeStatement;
CodeStatementCollection statements = serialized as CodeStatementCollection;
if (statement != null || statements != null) {
CodeStatementCollection contextStatements = null;
StatementContext context = manager.Context[typeof (StatementContext)] as StatementContext;
if (context != null && instance != null)
contextStatements = context.StatementCollection[instance];
if (contextStatements == null)
contextStatements = manager.Context[typeof (CodeStatementCollection)] as CodeStatementCollection;
if (contextStatements != null) {
if (statements != null)
contextStatements.AddRange (statements);
else
contextStatements.Add (statement);
}
}
}
if (expression == null && instance != null)
expression = this.GetExpression (manager, instance); // 4
} else {
ReportError (manager, "No serializer found for type '" + instance.GetType ().Name + "'");
}
}
return expression;
}
protected CodeDomSerializer GetSerializer (IDesignerSerializationManager manager, object instance)
{
DesignerSerializerAttribute attrInstance, attrType;
attrType = attrInstance = null;
CodeDomSerializer serializer = null;
if (instance == null)
serializer = this.GetSerializer (manager, null);
else {
AttributeCollection attributes = TypeDescriptor.GetAttributes (instance);
foreach (Attribute a in attributes) {
DesignerSerializerAttribute designerAttr = a as DesignerSerializerAttribute;
if (designerAttr != null && manager.GetType (designerAttr.SerializerBaseTypeName) == typeof (CodeDomSerializer)) {
attrInstance = designerAttr;
break;
}
}
attributes = TypeDescriptor.GetAttributes (instance.GetType ());
foreach (Attribute a in attributes) {
DesignerSerializerAttribute designerAttr = a as DesignerSerializerAttribute;
if (designerAttr != null && manager.GetType (designerAttr.SerializerBaseTypeName) == typeof (CodeDomSerializer)) {
attrType = designerAttr;
break;
}
}
// if there is metadata modification in the instance then create the specified serializer instead of the one
// in the Type.
if (attrType != null && attrInstance != null && attrType.SerializerTypeName != attrInstance.SerializerTypeName)
serializer = Activator.CreateInstance (manager.GetType (attrInstance.SerializerTypeName)) as CodeDomSerializer;
else
serializer = this.GetSerializer (manager, instance.GetType ());
}
return serializer;
}
protected CodeDomSerializer GetSerializer (IDesignerSerializationManager manager, Type instanceType)
{
return manager.GetSerializer (instanceType, typeof (CodeDomSerializer)) as CodeDomSerializer;
}
protected CodeExpression GetExpression (IDesignerSerializationManager manager, object instance)
{
if (manager == null)
throw new ArgumentNullException ("manager");
if (instance == null)
throw new ArgumentNullException ("instance");
CodeExpression expression = null;
ExpressionTable expressions = manager.Context[typeof (ExpressionTable)] as ExpressionTable;
if (expressions != null) // 1st try: ExpressionTable
expression = expressions [instance] as CodeExpression;
if (expression == null) { // 2nd try: RootContext
RootContext context = manager.Context[typeof (RootContext)] as RootContext;
if (context != null && context.Value == instance)
expression = context.Expression;
}
if (expression == null) { // 3rd try: IReferenceService (instance.property.property.property
string name = manager.GetName (instance);
if (name == null || name.IndexOf (".") == -1) {
IReferenceService service = manager.GetService (typeof (IReferenceService)) as IReferenceService;
if (service != null) {
name = service.GetName (instance);
if (name != null && name.IndexOf (".") != -1) {
string[] parts = name.Split (new char[] { ',' });
instance = manager.GetInstance (parts[0]);
if (instance != null) {
expression = SerializeToExpression (manager, instance);
if (expression != null) {
for (int i=1; i < parts.Length; i++)
expression = new CodePropertyReferenceExpression (expression, parts[i]);
}
}
}
}
}
}
return expression;
}
protected void SetExpression (IDesignerSerializationManager manager, object instance, CodeExpression expression)
{
SetExpression (manager, instance, expression, false);
}
// XXX: isPreset - what does this do when set?
//
protected void SetExpression (IDesignerSerializationManager manager, object instance, CodeExpression expression, bool isPreset)
{
if (manager == null)
throw new ArgumentNullException ("manager");
if (instance == null)
throw new ArgumentNullException ("instance");
if (expression == null)
throw new ArgumentNullException ("expression");
ExpressionTable expressions = manager.Context[typeof (ExpressionTable)] as ExpressionTable;
if (expressions == null) {
expressions = new ExpressionTable ();
manager.Context.Append (expressions);
}
expressions[instance] = expression;
}
protected bool IsSerialized (IDesignerSerializationManager manager, object value)
{
return this.IsSerialized (manager, value, false);
}
// XXX: What should honorPreset do?
protected bool IsSerialized (IDesignerSerializationManager manager, object instance, bool honorPreset)
{
if (instance == null)
throw new ArgumentNullException ("instance");
if (manager == null)
throw new ArgumentNullException ("manager");
if (this.GetExpression (manager, instance) != null)
return true;
else
return false;
}
protected CodeExpression SerializeCreationExpression (IDesignerSerializationManager manager, object value, out bool isComplete)
{
if (value == null)
throw new ArgumentNullException ("value");
if (manager == null)
throw new ArgumentNullException ("manager");
CodeExpression expression = null;
TypeConverter converter = TypeDescriptor.GetConverter (value);
if (converter != null && converter.CanConvertTo (typeof (InstanceDescriptor))) {
InstanceDescriptor descriptor = converter.ConvertTo (value, typeof (InstanceDescriptor)) as InstanceDescriptor;
isComplete = descriptor.IsComplete;
if (descriptor != null || descriptor.MemberInfo != null)
expression = this.SerializeInstanceDescriptor (manager, descriptor);
else
ReportError (manager, "Unable to serialize to InstanceDescriptor",
"Value Type: " + value.GetType ().Name + System.Environment.NewLine +
"Value (ToString): " + value.ToString ());
} else {
if (value.GetType().GetConstructor (Type.EmptyTypes) != null)
expression = new CodeObjectCreateExpression (value.GetType ().FullName, new CodeExpression[0]);
isComplete = false;
}
return expression;
}
private CodeExpression SerializeInstanceDescriptor (IDesignerSerializationManager manager, InstanceDescriptor descriptor)
{
CodeExpression expression = null;
MemberInfo member = descriptor.MemberInfo;
CodeExpression target = new CodeTypeReferenceExpression (member.DeclaringType);
if (member is PropertyInfo) {
expression = new CodePropertyReferenceExpression (target, member.Name);
} else if (member is FieldInfo) {
expression = new CodeFieldReferenceExpression (target, member.Name);
} else if (member is MethodInfo) {
CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression (target, member.Name);
if (descriptor.Arguments != null && descriptor.Arguments.Count > 0)
methodInvoke.Parameters.AddRange (SerializeParameters (manager, descriptor.Arguments));
expression = methodInvoke;
} else if (member is ConstructorInfo) {
CodeObjectCreateExpression createExpr = new CodeObjectCreateExpression (member.DeclaringType);
if (descriptor.Arguments != null && descriptor.Arguments.Count > 0)
createExpr.Parameters.AddRange (SerializeParameters (manager, descriptor.Arguments));
expression = createExpr;
}
return expression;
}
private CodeExpression[] SerializeParameters (IDesignerSerializationManager manager, ICollection parameters)
{
CodeExpression[] expressions = null;
if (parameters != null && parameters.Count > 0) {
expressions = new CodeExpression[parameters.Count];
int i = 0;
foreach (object parameter in parameters) {
expressions[i] = this.SerializeToExpression (manager, parameter);
i++;
}
}
return expressions;
}
protected void SerializeEvent (IDesignerSerializationManager manager, CodeStatementCollection statements,
object value, EventDescriptor descriptor)
{
if (descriptor == null)
throw new ArgumentNullException ("descriptor");
if (value == null)
throw new ArgumentNullException ("value");
if (statements == null)
throw new ArgumentNullException ("statements");
if (manager == null)
throw new ArgumentNullException ("manager");
MemberCodeDomSerializer serializer = manager.GetSerializer (descriptor.GetType (), typeof (MemberCodeDomSerializer)) as MemberCodeDomSerializer;
if (serializer != null && serializer.ShouldSerialize (manager, value, descriptor))
serializer.Serialize (manager, value, descriptor, statements);
}
protected void SerializeEvents (IDesignerSerializationManager manager, CodeStatementCollection statements,
object value, params Attribute[] filter)
{
if (filter == null)
throw new ArgumentNullException ("filter");
if (value == null)
throw new ArgumentNullException ("value");
if (statements == null)
throw new ArgumentNullException ("statements");
if (manager == null)
throw new ArgumentNullException ("manager");
EventDescriptorCollection events = TypeDescriptor.GetEvents (value, filter);
foreach (EventDescriptor e in events)
this.SerializeEvent (manager, statements, value, e);
}
protected void SerializeProperty (IDesignerSerializationManager manager, CodeStatementCollection statements,
object value, PropertyDescriptor propertyToSerialize)
{
if (propertyToSerialize == null)
throw new ArgumentNullException ("propertyToSerialize");
if (value == null)
throw new ArgumentNullException ("value");
if (statements == null)
throw new ArgumentNullException ("statements");
if (manager == null)
throw new ArgumentNullException ("manager");
MemberCodeDomSerializer serializer = manager.GetSerializer (propertyToSerialize.GetType (),
typeof (MemberCodeDomSerializer)) as MemberCodeDomSerializer;
if (serializer != null && serializer.ShouldSerialize (manager, value, propertyToSerialize))
serializer.Serialize (manager, value, propertyToSerialize, statements);
}
protected void SerializeProperties (IDesignerSerializationManager manager, CodeStatementCollection statements,
object value, Attribute[] filter)
{
if (filter == null)
throw new ArgumentNullException ("filter");
if (value == null)
throw new ArgumentNullException ("value");
if (statements == null)
throw new ArgumentNullException ("statements");
if (manager == null)
throw new ArgumentNullException ("manager");
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties (value, filter);
foreach (PropertyDescriptor property in properties) {
if (!property.Attributes.Contains (DesignerSerializationVisibilityAttribute.Hidden))
this.SerializeProperty (manager, statements, value, property);
}
}
protected virtual object DeserializeInstance (IDesignerSerializationManager manager, Type type,
object[] parameters, string name, bool addToContainer)
{
if (type == null)
throw new ArgumentNullException ("type");
if (manager == null)
throw new ArgumentNullException ("manager");
return manager.CreateInstance (type, parameters, name, addToContainer);
}
protected string GetUniqueName (IDesignerSerializationManager manager, object instance)
{
if (instance == null)
throw new ArgumentNullException ("instance");
if (manager == null)
throw new ArgumentNullException ("manager");
string name = manager.GetName (instance);
if (name == null) {
INameCreationService service = manager.GetService (typeof (INameCreationService)) as INameCreationService;
name = service.CreateName (null, instance.GetType ());
if (name == null)
name = instance.GetType ().Name.ToLower ();
manager.SetName (instance, name);
}
return name;
}
protected object DeserializeExpression (IDesignerSerializationManager manager, string name, CodeExpression expression)
{
if (expression == null)
throw new ArgumentNullException ("expression");
if (manager == null)
throw new ArgumentNullException ("manager");
bool errorOccurred = false;
object deserialized = null;
// CodeThisReferenceExpression
//
CodeThisReferenceExpression thisExpr = expression as CodeThisReferenceExpression;
if (thisExpr != null) {
RootContext context = manager.Context[typeof (RootContext)] as RootContext;
if (context != null) {
deserialized = context.Value;
} else {
IDesignerHost host = manager.GetService (typeof (IDesignerHost)) as IDesignerHost;
if (host != null)
deserialized = host.RootComponent;
}
}
// CodeVariableReferenceExpression
//
CodeVariableReferenceExpression varRef = expression as CodeVariableReferenceExpression;
if (deserialized == null && varRef != null) {
deserialized = manager.GetInstance (varRef.VariableName);
if (deserialized == null) {
ReportError (manager, "Variable '" + varRef.VariableName + "' not initialized prior to reference");
errorOccurred = true;
}
}
// CodeFieldReferenceExpression (used for Enum references as well)
//
CodeFieldReferenceExpression fieldRef = expression as CodeFieldReferenceExpression;
if (deserialized == null && fieldRef != null) {
deserialized = manager.GetInstance (fieldRef.FieldName);
if (deserialized == null) {
object fieldHolder = DeserializeExpression (manager, null, fieldRef.TargetObject);
FieldInfo field = null;
if (fieldHolder is Type) // static field
field = ((Type)fieldHolder).GetField (fieldRef.FieldName,
BindingFlags.GetField | BindingFlags.Public | BindingFlags.Static);
else // instance field
field = fieldHolder.GetType().GetField (fieldRef.FieldName,
BindingFlags.GetField | BindingFlags.Public | BindingFlags.Instance);
if (field != null)
deserialized = field.GetValue (fieldHolder);
}
if (deserialized == null)
ReportError (manager, "Field '" + fieldRef.FieldName + "' not initialized prior to reference");
}
// CodePrimitiveExpression
//
CodePrimitiveExpression primitiveExp = expression as CodePrimitiveExpression;
if (deserialized == null && primitiveExp != null)
deserialized = primitiveExp.Value;
// CodePropertyReferenceExpression
//
CodePropertyReferenceExpression propRef = expression as CodePropertyReferenceExpression;
if (deserialized == null && propRef != null) {
object target = DeserializeExpression (manager, null, propRef.TargetObject);
if (target != null && target != _errorMarker) {
bool found = false;
if (target is Type) {
PropertyInfo property = ((Type)target).GetProperty (propRef.PropertyName,
BindingFlags.GetProperty |
BindingFlags.Public | BindingFlags.Static);
if (property != null) {
deserialized = property.GetValue (null, null);
found = true;
}
// NRefactory seems to produce PropertyReferences to reference some fields and enums
//
FieldInfo field = ((Type)target).GetField (propRef.PropertyName,
BindingFlags.GetField | BindingFlags.Public | BindingFlags.Static);
if (field != null) {
deserialized = field.GetValue (null);
found = true;
}
} else {
PropertyDescriptor property = TypeDescriptor.GetProperties (target)[propRef.PropertyName];
if (property != null) {
deserialized = property.GetValue (target);
found = true;
}
FieldInfo field = target.GetType().GetField (propRef.PropertyName,
BindingFlags.GetField | BindingFlags.Public | BindingFlags.Instance);
if (field != null) {
deserialized = field.GetValue (null);
found = true;
}
}
if (!found) {
ReportError (manager, "Missing field '" + propRef.PropertyName + " 'in type " +
(target is Type ? ((Type)target).Name : target.GetType ().Name) + "'");
errorOccurred = true;
}
}
}
// CodeObjectCreateExpression
//
CodeObjectCreateExpression createExpr = expression as CodeObjectCreateExpression;
if (deserialized == null && createExpr != null) {
Type type = manager.GetType (createExpr.CreateType.BaseType);
if (type == null) {
ReportError (manager, "Type '" + createExpr.CreateType.BaseType + "' not found." +
"Are you missing a reference?");
errorOccurred = true;
} else {
object[] arguments = new object[createExpr.Parameters.Count];
for (int i=0; i < createExpr.Parameters.Count; i++) {
arguments[i] = this.DeserializeExpression (manager, null, createExpr.Parameters[i]);
if (arguments[i] == _errorMarker) {
errorOccurred = true;
break;
}
}
if (!errorOccurred) {
bool addToContainer = false;
if (typeof(IComponent).IsAssignableFrom (type))
addToContainer = true;
deserialized = this.DeserializeInstance (manager, type, arguments, name, addToContainer);
if (deserialized == _errorMarker || deserialized == null) {
string info = "Type to create: " + createExpr.CreateType.BaseType + System.Environment.NewLine +
"Name: " + name + System.Environment.NewLine +
"addToContainer: " + addToContainer.ToString () + System.Environment.NewLine +
"Parameters Count: " + createExpr.Parameters.Count + System.Environment.NewLine;
for (int i=0; i < arguments.Length; i++) {
info += "Parameter Number: " + i.ToString () + System.Environment.NewLine +
"Parameter Type: " + (arguments[i] == null ? "null" : arguments[i].GetType ().Name) +
System.Environment.NewLine +
"Parameter '" + i.ToString () + "' Value: " + arguments[i].ToString () + System.Environment.NewLine;
}
ReportError (manager,
"Unable to create an instance of type '" + createExpr.CreateType.BaseType + "'",
info);
errorOccurred = true;
}
}
}
}
// CodeArrayCreateExpression
//
CodeArrayCreateExpression arrayCreateExpr = expression as CodeArrayCreateExpression;
if (deserialized == null && arrayCreateExpr != null) {
Type arrayType = manager.GetType (arrayCreateExpr.CreateType.BaseType);
if (arrayType == null) {
ReportError (manager, "Type '" + arrayCreateExpr.CreateType.BaseType + "' not found." +
"Are you missing a reference?");
errorOccurred = true;
} else {
ArrayList initializers = new ArrayList ();
Type elementType = arrayType.GetElementType ();
deserialized = Array.CreateInstance (arrayType, arrayCreateExpr.Initializers.Count);
for (int i = 0; i < arrayCreateExpr.Initializers.Count; i++) {
object element = this.DeserializeExpression (manager, null, arrayCreateExpr.Initializers[i]);
errorOccurred = (element == _errorMarker);
if (!errorOccurred) {
if (arrayType.IsInstanceOfType (element)) {
initializers.Add (element);
} else {
ReportError (manager,
"Array initializer element type incompatible with array type.",
"Array Type: " + arrayType.Name + System.Environment.NewLine +
"Array Element Type: " + elementType + System.Environment.NewLine +
"Initializer Type: " + (element == null ? "null" : element.GetType ().Name));
errorOccurred = true;
}
}
}
if (!errorOccurred)
initializers.CopyTo ((Array)deserialized, 0);
}
}
// CodeMethodInvokeExpression
//
CodeMethodInvokeExpression methodExpr = expression as CodeMethodInvokeExpression;
if (deserialized == null && methodExpr != null) {
object target = this.DeserializeExpression (manager, null, methodExpr.Method.TargetObject);
object[] parameters = null;
if (target == _errorMarker || target == null) {
errorOccurred = true;
} else {
parameters = new object[methodExpr.Parameters.Count];
for (int i=0; i < methodExpr.Parameters.Count; i++) {
parameters[i] = this.DeserializeExpression (manager, null, methodExpr.Parameters[i]);
if (parameters[i] == _errorMarker) {
errorOccurred = true;
break;
}
}
}
if (!errorOccurred) {
MethodInfo method = null;
if (target is Type) {
method = GetExactMethod ((Type)target, methodExpr.Method.MethodName,
BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
parameters);
} else {
method = GetExactMethod (target.GetType(), methodExpr.Method.MethodName,
BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance,
parameters);
}
if (method != null) {
deserialized = method.Invoke (target, parameters);
} else {
string info =
"Method Name: " + methodExpr.Method.MethodName + System.Environment.NewLine +
"Method is: " + (target is Type ? "static" : "instance") + System.Environment.NewLine +
"Method Holder Type: " + (target is Type ? ((Type)target).Name : target.GetType ().Name) + System.Environment.NewLine +
"Parameters Count: " + methodExpr.Parameters.Count + System.Environment.NewLine +
System.Environment.NewLine;
for (int i = 0; i < parameters.Length; i++) {
info += "Parameter Number: " + i.ToString () + System.Environment.NewLine +
"Parameter Type: " + (parameters[i] == null ? "null" : parameters[i].GetType ().Name) +
System.Environment.NewLine +
"Parameter " + i.ToString () + " Value: " + parameters[i].ToString () + System.Environment.NewLine;
}
ReportError (manager,
"Method '" + methodExpr.Method.MethodName + "' missing in type '" +
(target is Type ? ((Type)target).Name : target.GetType ().Name + "'"),
info);
errorOccurred = true;
}
}
}
// CodeTypeReferenceExpression
//
CodeTypeReferenceExpression typeRef = expression as CodeTypeReferenceExpression;
if (deserialized == null && typeRef != null) {
deserialized = manager.GetType (typeRef.Type.BaseType);
if (deserialized == null) {
ReportError (manager, "Type '" + typeRef.Type.BaseType + "' not found." +
"Are you missing a reference?");
errorOccurred = true;
}
}
// CodeCastExpression
//
CodeCastExpression castExpr = expression as CodeCastExpression;
if (deserialized == null && castExpr != null) {
Type targetType = manager.GetType (castExpr.TargetType.BaseType);
object instance = DeserializeExpression (manager, null, castExpr.Expression);
if (instance != null && instance != _errorMarker && targetType != null) {
IConvertible convertible = instance as IConvertible;
if (convertible != null) {
try {
instance = convertible.ToType (targetType, null);
} catch {
errorOccurred = true;
}
} else {
errorOccurred = true;
}
if (errorOccurred) {
ReportError (manager, "Unable to convert type '" + instance.GetType ().Name +
"' to type '" + castExpr.TargetType.BaseType + "'",
"Target Type: " + castExpr.TargetType.BaseType + System.Environment.NewLine +
"Instance Type: " + (instance == null ? "null" : instance.GetType ().Name) + System.Environment.NewLine +
"Instance Value: " + (instance == null ? "null" : instance.ToString()) + System.Environment.NewLine +
"Instance is IConvertible: " + (instance is IConvertible).ToString());
}
deserialized = instance;
}
}
// CodeBinaryOperatorExpression
//
CodeBinaryOperatorExpression binOperator = expression as CodeBinaryOperatorExpression;
if (deserialized == null && binOperator != null) {
string errorText = null;
IConvertible left = null;
IConvertible right = null;
switch (binOperator.Operator) {
case CodeBinaryOperatorType.BitwiseOr:
left = DeserializeExpression (manager, null, binOperator.Left) as IConvertible;
right = DeserializeExpression (manager, null, binOperator.Right) as IConvertible;
if (left is Enum && right is Enum) {
deserialized = Enum.ToObject (left.GetType (), Convert.ToInt64 (left) | Convert.ToInt64 (right));
} else {
errorText = "CodeBinaryOperatorType.BitwiseOr allowed only on Enum types";
errorOccurred = true;
}
break;
default:
errorText = "Unsupported CodeBinaryOperatorType: " + binOperator.Operator.ToString ();
errorOccurred = true;
break;
}
if (errorOccurred) {
string info = "BinaryOperator Type: " + binOperator.Operator.ToString() + System.Environment.NewLine +
"Left Type: " + (left == null ? "null" : left.GetType().Name) + System.Environment.NewLine +
"Left Value: " + (left == null ? "null" : left.ToString ()) + System.Environment.NewLine +
"Left Expression Type: " + binOperator.Left.GetType ().Name + System.Environment.NewLine +
"Right Type: " + (right == null ? "null" : right.GetType().Name) + System.Environment.NewLine +
"Right Value: " + (right == null ? "null" : right.ToString ()) + System.Environment.NewLine +
"Right Expression Type: " + binOperator.Right.GetType ().Name;
ReportError (manager, errorText, info);
}
}
if (!errorOccurred) {
if (deserialized == null && !(expression is CodePrimitiveExpression) && !(expression is CodeMethodInvokeExpression)) {
ReportError (manager, "Unsupported Expression Type: " + expression.GetType ().Name);
errorOccurred = true;
}
}
if (errorOccurred)
deserialized = _errorMarker;
return deserialized;
}
// Searches for a method on type that matches argument types
//
private MethodInfo GetExactMethod (Type type, string methodName, BindingFlags flags, ICollection argsCollection)
{
object[] arguments = null;
Type[] types = Type.EmptyTypes;
if (argsCollection != null) {
arguments = new object[argsCollection.Count];
types = new Type[argsCollection.Count];
argsCollection.CopyTo (arguments, 0);
for (int i=0; i < arguments.Length; i++) {
if (arguments[i] == null)
types[i] = null;
else
types[i] = arguments[i].GetType ();
}
}
return type.GetMethod (methodName, flags, null, types, null);
}
protected void DeserializeStatement (IDesignerSerializationManager manager, CodeStatement statement)
{
if (statement == null)
throw new ArgumentNullException ("statement");
if (manager == null)
throw new ArgumentNullException ("manager");
// CodeAssignStatement
//
CodeAssignStatement assignment = statement as CodeAssignStatement;
if (assignment != null)
DeserializeAssignmentStatement (manager, assignment);
// CodeExpressionStatement
//
CodeExpressionStatement expression = statement as CodeExpressionStatement;
if (expression != null)
this.DeserializeExpression (manager, null, expression.Expression);
// CodeAttachEventStatement
//
CodeAttachEventStatement attachStatement = statement as CodeAttachEventStatement;
if (attachStatement != null) {
string methodName = null;
CodeObjectCreateExpression createExpr = attachStatement.Listener as CodeObjectCreateExpression;
if (createExpr != null && createExpr.Parameters.Count == 1 ) { // += new EventType (method)
CodeMethodReferenceExpression handlerRef = createExpr.Parameters[0] as CodeMethodReferenceExpression;
if (handlerRef != null)
methodName = handlerRef.MethodName;
}
CodeDelegateCreateExpression delegateCreateExpr = attachStatement.Listener as CodeDelegateCreateExpression;
if (delegateCreateExpr != null)// += new EventType (method)
methodName = delegateCreateExpr.MethodName;
CodeMethodReferenceExpression methodRef = attachStatement.Listener as CodeMethodReferenceExpression;
if (methodRef != null) // += method
methodName = methodRef.MethodName;
object component = DeserializeExpression (manager, null, attachStatement.Event.TargetObject);
if (component != null && component != _errorMarker && methodName != null) {
string error = null;
EventDescriptor eventDescriptor = TypeDescriptor.GetEvents (component)[attachStatement.Event.EventName];
if (eventDescriptor != null) {
IEventBindingService service = manager.GetService (typeof (IEventBindingService)) as IEventBindingService;
if (service != null)
service.GetEventProperty (eventDescriptor).SetValue (component, methodName);
else
error = "IEventBindingService missing";
} else {
error = "No event '" + attachStatement.Event.EventName +
"' found in type '" + component.GetType ().Name + "'";
}
if (error != null) {
ReportError (manager, error, "Method Name: " + methodName + System.Environment.NewLine +
"Event Name: " + attachStatement.Event.EventName + System.Environment.NewLine +
"Listener Expression Type: " + methodRef.GetType ().Name + System.Environment.NewLine +
"Event Holder Type: " + component.GetType ().Name + System.Environment.NewLine +
"Event Holder Expression Type: " + attachStatement.Event.TargetObject.GetType ().Name);
}
}
}
}
private void DeserializeAssignmentStatement (IDesignerSerializationManager manager, CodeAssignStatement statement)
{
CodeExpression leftExpr = statement.Left;
// Assign to a Property
//
CodePropertyReferenceExpression propRef = leftExpr as CodePropertyReferenceExpression;
if (propRef != null) {
object propertyHolder = DeserializeExpression (manager, null, propRef.TargetObject);
object value = null;
if (propertyHolder != null && propertyHolder != _errorMarker)
value = DeserializeExpression (manager, null, statement.Right);
if (value != null && value != _errorMarker && propertyHolder != null) {
PropertyDescriptor property = TypeDescriptor.GetProperties (propertyHolder)[propRef.PropertyName];
if (property != null) {
property.SetValue (propertyHolder, value);
} else {
ReportError (manager,
"Missing property '" + propRef.PropertyName +
"' in type '" + propertyHolder.GetType ().Name + "'");
}
}
}
// Assign to a Field
//
CodeFieldReferenceExpression fieldRef = leftExpr as CodeFieldReferenceExpression;
if (fieldRef != null && fieldRef.FieldName != null) {
// Note that if the Right expression is a CodeCreationExpression the component will be created in this call
//
object fieldHolder = DeserializeExpression (manager, null, fieldRef.TargetObject);
object value = null;
if (fieldHolder != null && fieldHolder != _errorMarker)
value = DeserializeExpression (manager, fieldRef.FieldName, statement.Right);
FieldInfo field = null;
RootContext context = manager.Context[typeof (RootContext)] as RootContext;
if (fieldHolder != null && fieldHolder != _errorMarker && value != _errorMarker) {
if (fieldRef.TargetObject is CodeThisReferenceExpression && context != null && context.Value == fieldHolder) {
// Do not deserialize the fields of the root component, because the root component type
// is actually an instance of the its parent type, e.g: CustomControl : _UserControl_
// and thus it doesn't contain the fields. The trick is that once DeserializeExpression
// is called on a CodeObjectCreateExpression the component is created and is added to the name-instance
// table.
//
} else {
if (fieldHolder is Type) // static field
field = ((Type)fieldHolder).GetField (fieldRef.FieldName,
BindingFlags.GetField | BindingFlags.Public | BindingFlags.Static);
else // instance field
field = fieldHolder.GetType().GetField (fieldRef.FieldName,
BindingFlags.GetField | BindingFlags.Public | BindingFlags.Instance);
if (field != null)
field.SetValue (fieldHolder, value);
else {
ReportError (manager, "Field '" + fieldRef.FieldName + "' missing in type '" +
fieldHolder.GetType ().Name + "'",
"Field Name: " + fieldRef.FieldName + System.Environment.NewLine +
"Field is: " + (fieldHolder is Type ? "static" : "instance") + System.Environment.NewLine +
"Field Value: " + (value == null ? "null" : value.ToString()) + System.Environment.NewLine +
"Field Holder Type: " + fieldHolder.GetType ().Name + System.Environment.NewLine +
"Field Holder Expression Type: " + fieldRef.TargetObject.GetType ().Name);
}
}
}
}
// Assign to a Variable
//
CodeVariableReferenceExpression varRef = leftExpr as CodeVariableReferenceExpression;
if (varRef != null && varRef.VariableName != null) {
object value = DeserializeExpression (manager, varRef.VariableName, statement.Right);
// If .Right is not CodeObjectCreateExpression the instance won't be assigned a name,
// so do it ourselves
if (value != _errorMarker && manager.GetName (value) == null)
manager.SetName (value, varRef.VariableName);
}
}
internal void ReportError (IDesignerSerializationManager manager, string message)
{
this.ReportError (manager, message, String.Empty);
}
internal void ReportError (IDesignerSerializationManager manager, string message, string details)
{
try {
throw new Exception (message);
} catch (Exception e) {
e.Data["Details"] = message + Environment.NewLine + Environment.NewLine + details;
manager.ReportError (e);
}
}
#region Resource Serialization - TODO
protected CodeExpression SerializeToResourceExpression (IDesignerSerializationManager manager, object value)
{
throw new NotImplementedException ();
}
protected CodeExpression SerializeToResourceExpression (IDesignerSerializationManager manager, object value,
bool ensureInvariant)
{
throw new NotImplementedException ();
}
protected void SerializePropertiesToResources (IDesignerSerializationManager manager, CodeStatementCollection statements,
object value, Attribute[] filter)
{
throw new NotImplementedException ();
}
protected void SerializeResource (IDesignerSerializationManager manager, string resourceName, object value)
{
throw new NotImplementedException ();
}
protected void SerializeResourceInvariant (IDesignerSerializationManager manager, string resourceName, object value)
{
throw new NotImplementedException ();
}
protected void DeserializePropertiesFromResources (IDesignerSerializationManager manager, object value, Attribute[] filter)
{
throw new NotImplementedException ();
}
#endregion
}
}
#endif
|