2
0
Эх сурвалжийг харах

2005-01-28 Lluis Sanchez Gual <[email protected]>

	* TemplateControlCompiler.cs: When generating a property value,
	check for TypeConverterAttribute in the PropertyInfo, not only in the
	property type.
	Implemented code generation using InstanceDescriptor, when the type
	converter supports conversion to that type.


svn path=/trunk/mcs/; revision=40094
Lluis Sanchez 21 жил өмнө
parent
commit
4fa3f910d8

+ 8 - 0
mcs/class/System.Web/System.Web.Compilation/ChangeLog

@@ -1,3 +1,11 @@
+2005-01-28  Lluis Sanchez Gual <[email protected]>
+
+	* TemplateControlCompiler.cs: When generating a property value,
+	check for TypeConverterAttribute in the PropertyInfo, not only in the
+	property type.
+	Implemented code generation using InstanceDescriptor, when the type
+	converter supports conversion to that type.
+
 2005-01-21  Lluis Sanchez Gual <[email protected]>
 
 	* Directive.cs: Added MASTER directive.

+ 98 - 91
mcs/class/System.Web/System.Web.Compilation/TemplateControlCompiler.cs

@@ -37,6 +37,7 @@ using System.Reflection;
 using System.Text;
 using System.Web;
 using System.Web.UI;
+using System.ComponentModel.Design.Serialization;
 
 namespace System.Web.Compilation
 {
@@ -267,7 +268,7 @@ namespace System.Web.Compilation
 			return method.Name;
 		}
 
-		void AddCodeForPropertyOrField (ControlBuilder builder, Type type, string var_name, string att, bool isDataBound)
+		void AddCodeForPropertyOrField (ControlBuilder builder, Type type, string var_name, string att, MemberInfo member, bool isDataBound)
 		{
 			CodeMemberMethod method = builder.method;
 			if (isDataBound) {
@@ -279,7 +280,7 @@ namespace System.Web.Compilation
 			CodeAssignStatement assign = new CodeAssignStatement ();
 			assign.Left = new CodePropertyReferenceExpression (ctrlVar, var_name);
 			currentLocation = builder.location;
-			assign.Right = GetExpressionFromString (type, att);
+			assign.Right = GetExpressionFromString (type, att, member);
 
 			method.Statements.Add (assign);
 		}
@@ -311,7 +312,7 @@ namespace System.Web.Compilation
 			}
 
 			if (0 == String.Compare (member.Name, id, true)){
-				AddCodeForPropertyOrField (builder, type, member.Name, attValue, isDataBound);
+				AddCodeForPropertyOrField (builder, type, member.Name, attValue, member, isDataBound);
 				return true;
 			}
 			
@@ -343,7 +344,7 @@ namespace System.Web.Compilation
 
 				AddCodeForPropertyOrField (builder, subprop.PropertyType,
 						 member.Name + "." + subprop.Name,
-						 value, isDataBound);
+						 value, subprop, isDataBound);
 				is_processed = true;
 			}
 
@@ -899,7 +900,7 @@ namespace System.Web.Compilation
 			mainClass.Members.Add (prop);
 		}
 		
-		CodeExpression GetExpressionFromString (Type type, string str)
+		CodeExpression GetExpressionFromString (Type type, string str, MemberInfo member)
 		{
 			if (type == typeof (string))
 				return new CodePrimitiveExpression (str);
@@ -918,21 +919,7 @@ namespace System.Web.Compilation
 				return new CodePrimitiveExpression (null);
 
 			if (type.IsPrimitive)
-				return new CodePrimitiveExpression (Convert.ChangeType (str, type));
-
-			if (type.IsEnum) {
-				object val = null;
-				try {
-					val = Enum.Parse (type, str, true);
-				} catch (Exception) {
-					throw new ParseException (currentLocation,
-							str + " is not a valid value for enum '" + type + "'");
-				}
-				CodeFieldReferenceExpression expr = new CodeFieldReferenceExpression ();
-				expr.TargetObject = new CodeTypeReferenceExpression (type);
-				expr.FieldName = val.ToString ();
-				return expr;
-			}
+				return new CodePrimitiveExpression (Convert.ChangeType (str, type, CultureInfo.InvariantCulture));
 
 			if (type == typeof (string [])) {
 				string [] subs = str.Split (',');
@@ -945,30 +932,6 @@ namespace System.Web.Compilation
 				return expr;
 			}
 
-			if (type == typeof (Size)) {
-				string [] subs = str.Split (',');
-				if (subs.Length != 2)
-					throw new ParseException (currentLocation,
-						String.Format ("Cannot create {0} from '{1}'", type, str));
-
-				int width = 0;
-				int height = 0;
-				try {
-					width = Int32.Parse (subs [0]);
-					height = Int32.Parse (subs [0]);
-					new Size (width, height);
-				} catch {
-					throw new ParseException (currentLocation,
-						String.Format ("Cannot create {0} from '{1}'", type, str));
-				}
-				
-				CodeObjectCreateExpression expr = new CodeObjectCreateExpression ();
-				expr.CreateType = new CodeTypeReference (type);
-				expr.Parameters.Add (new CodePrimitiveExpression (width));
-				expr.Parameters.Add (new CodePrimitiveExpression (height));
-				return expr;
-			}
-
 			if (type == typeof (Color)){
 				if (colorConverter == null)
 					colorConverter = TypeDescriptor.GetConverter (typeof (Color));
@@ -1018,63 +981,107 @@ namespace System.Web.Compilation
 				}
 			}
 
-			TypeConverter converter = TypeDescriptor.GetConverter (type);
-			if (converter != null && converter.CanConvertFrom (typeof (string))) {
-				CodeMethodReferenceExpression m = new CodeMethodReferenceExpression ();
-				m.TargetObject = new CodeTypeReferenceExpression (typeof (TypeDescriptor));
-				m.MethodName = "GetConverter";
-				CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (m);
-				CodeTypeReference tref = new CodeTypeReference (type);
-				invoke.Parameters.Add (new CodeTypeOfExpression (tref));
-				
-				invoke = new CodeMethodInvokeExpression (invoke, "ConvertFrom");
-				invoke.Parameters.Add (new CodePrimitiveExpression (str));
-
-				return new CodeCastExpression (tref, invoke);
-			}
-
-			bool parms = false;
-			BindingFlags flags = BindingFlags.Public | BindingFlags.Static;
-			MethodInfo parse = type.GetMethod ("Parse", flags, null, arrayStringCultureInfo, null);
-			if (parse != null) {
-				parms = true;
+			TypeConverter converter = null;
+			
+			TypeConverterAttribute at = (TypeConverterAttribute) Attribute.GetCustomAttribute (member, typeof(TypeConverterAttribute), true);
+			if (at != null) {
+				Type t = Type.GetType (at.ConverterTypeName);
+				converter = (TypeConverter) Activator.CreateInstance (t);
 			} else {
-				parse = type.GetMethod ("Parse", flags, null, arrayString, null);
+				converter = TypeDescriptor.GetConverter (type);
 			}
+			
+			if (converter != null && converter.CanConvertFrom (typeof (string)))
+			{
+				object value = converter.ConvertFrom (str);
 
-			if (parse != null) {
-				object o = null;
-				try {
-					if (parms)
-						o = parse.Invoke (null, new object [] { str, CultureInfo.InvariantCulture });
-					else
-						o = parse.Invoke (null, new object [] { str });
-				} catch (Exception e) {
-					throw new ParseException (currentLocation, "Cannot parse " + str + " as " + type, e);
+				if (converter.CanConvertTo (typeof (InstanceDescriptor))) {
+					InstanceDescriptor idesc = (InstanceDescriptor) converter.ConvertTo (value, typeof(InstanceDescriptor));
+					return GenerateInstance (idesc);
 				}
 				
-				if (o == null)
-					throw new ParseException (currentLocation, str + " as " + type + " is null");
-
-				CodeTypeReferenceExpression exprType = new CodeTypeReferenceExpression (type);
-				CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (exprType, "Parse");
-				//FIXME: may be we gotta ensure roundtrip between o.ToString and Parse
-				invoke.Parameters.Add (new CodePrimitiveExpression (o.ToString ()));
-				if (parms) {
-					CodeTypeReferenceExpression texp = new CodeTypeReferenceExpression (typeof (CultureInfo));
-					CodePropertyReferenceExpression pexp = new CodePropertyReferenceExpression ();
-					pexp.TargetObject = texp;
-					pexp.PropertyName = "InvariantCulture";
-					invoke.Parameters.Add (pexp);
-				}
-				return invoke;
+				InstanceDescriptor desc = GetDefaultInstanceDescriptor (value);
+				if (desc != null) return GenerateInstance (desc);
+				
+				return GenerateObjectInstance (value);
 			}
-
-			// FIXME: Arrays
+			
 			Console.WriteLine ("Unknown type: " + type + " value: " + str);
 
 			return new CodePrimitiveExpression (str);
 		}
+		
+		CodeExpression GenerateInstance (InstanceDescriptor idesc)
+		{
+			CodeExpression[] parameters = new CodeExpression [idesc.Arguments.Count];
+			int n = 0;
+			foreach (object ob in idesc.Arguments)
+				parameters [n++] = GenerateObjectInstance (ob);
+			
+			switch (idesc.MemberInfo.MemberType) {
+			case MemberTypes.Constructor:
+				CodeTypeReference tob = new CodeTypeReference (idesc.MemberInfo.DeclaringType);
+				return new CodeObjectCreateExpression (tob, parameters);
+
+			case MemberTypes.Method:
+				CodeTypeReferenceExpression mt = new CodeTypeReferenceExpression (idesc.MemberInfo.DeclaringType);
+				return new CodeMethodInvokeExpression (mt, idesc.MemberInfo.Name, parameters);
+
+			case MemberTypes.Field:
+				CodeTypeReferenceExpression ft = new CodeTypeReferenceExpression (idesc.MemberInfo.DeclaringType);
+				return new CodeFieldReferenceExpression (ft, idesc.MemberInfo.Name);
+
+			case MemberTypes.Property:
+				CodeTypeReferenceExpression pt = new CodeTypeReferenceExpression (idesc.MemberInfo.DeclaringType);
+				return new CodePropertyReferenceExpression (pt, idesc.MemberInfo.Name);
+			}
+			throw new ParseException (currentLocation, "Invalid instance type.");
+		}
+		
+		CodeExpression GenerateObjectInstance (object value)
+		{
+			if (value == null)
+				return new CodePrimitiveExpression (null);
+			
+			Type t = value.GetType();
+			if (t.IsPrimitive || value is string)
+				return new CodePrimitiveExpression (value);
+				
+			if (t.IsArray) {
+				Array ar = (Array) value;
+				CodeExpression[] items = new CodeExpression [ar.Length];
+				for (int n=0; n<ar.Length; n++)
+					items [n] = GenerateObjectInstance (ar.GetValue (n));
+				return new CodeArrayCreateExpression (new CodeTypeReference (t), items);
+			}
+			
+			TypeConverter converter = TypeDescriptor.GetConverter (t);
+			if (converter != null && converter.CanConvertTo (typeof (InstanceDescriptor))) {
+				InstanceDescriptor idesc = (InstanceDescriptor) converter.ConvertTo (value, typeof(InstanceDescriptor));
+				return GenerateInstance (idesc);
+			}
+			
+			InstanceDescriptor desc = GetDefaultInstanceDescriptor (value);
+			if (desc != null) return GenerateInstance (desc);
+			
+			throw new ParseException (currentLocation, "Cannot generate an instance for the type: " + t);
+		}
+		
+		InstanceDescriptor GetDefaultInstanceDescriptor (object value)
+		{
+			if (value is System.Web.UI.WebControls.Unit) {
+				System.Web.UI.WebControls.Unit s = (System.Web.UI.WebControls.Unit) value;
+				MethodInfo met = typeof(System.Web.UI.WebControls.Unit).GetMethod ("Parse", new Type[] {typeof(string)});
+				return new InstanceDescriptor (met, new object[] {s.ToString ()});
+			}
+			
+			if (value is System.Web.UI.WebControls.FontUnit) {
+				System.Web.UI.WebControls.FontUnit s = (System.Web.UI.WebControls.FontUnit) value;
+				MethodInfo met = typeof(System.Web.UI.WebControls.FontUnit).GetMethod ("Parse", new Type[] {typeof(string)});
+				return new InstanceDescriptor (met, new object[] {s.ToString ()});
+			}
+			return null;
+		}
 	}
 }