//
// (C) 2003 Ximian, Inc (http://www.ximian.com)
//
+
+//
+// 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.
+//
using System;
using System.CodeDom;
using System.Collections;
using System.Text;
using System.Web;
using System.Web.UI;
+using System.Web.Util;
+using System.ComponentModel.Design.Serialization;
+#if NET_2_0
+using System.Collections.Specialized;
+using System.Text.RegularExpressions;
+#endif
namespace System.Web.Compilation
{
static BindingFlags noCaseFlags = BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.IgnoreCase;
- static Type styleType = typeof (System.Web.UI.WebControls.Style);
- static Type fontinfoType = typeof (System.Web.UI.WebControls.FontInfo);
-
TemplateControlParser parser;
int dataBoundAtts;
ILocation currentLocation;
static TypeConverter colorConverter;
static CodeVariableReferenceExpression ctrlVar = new CodeVariableReferenceExpression ("__ctrl");
- static Type [] arrayString = new Type [] {typeof (string)};
- static Type [] arrayStringCultureInfo = new Type [] {typeof (string), typeof (CultureInfo)};
+
+#if NET_2_0
+ static Regex bindRegex = new Regex (@"Bind\s*\(""(.*?)""\)\s*%>", RegexOptions.Compiled);
+#endif
public TemplateControlCompiler (TemplateControlParser parser)
: base (parser)
initAsControl.Parameters.Add (new CodePropertyReferenceExpression (thisRef, "Page"));
method.Statements.Add (initAsControl);
}
+#if NET_2_0
+ if (typeof (System.Web.UI.WebControls.ContentPlaceHolder).IsAssignableFrom (type)) {
+ CodePropertyReferenceExpression prop = new CodePropertyReferenceExpression (thisRef, "ContentPlaceHolders");
+ CodeMethodInvokeExpression addPlaceholder = new CodeMethodInvokeExpression (prop, "Add");
+ addPlaceholder.Parameters.Add (ctrlVar);
+ method.Statements.Add (addPlaceholder);
+ }
+#endif
}
mainClass.Members.Add (method);
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) {
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);
}
return false;
string str = value.Trim ();
- return (str.StartsWith ("<%#") && str.EndsWith ("%>"));
+ return (StrUtils.StartsWith (str, "<%#") && StrUtils.EndsWith (str, "%>"));
}
-
- bool ProcessPropertiesAndFields (ControlBuilder builder, MemberInfo member, string id, string attValue)
+
+#if NET_2_0
+ void RegisterBindingInfo (ControlBuilder builder, string propName, ref string value)
{
- CodeMemberMethod method = builder.method;
- int hyphen = id.IndexOf ('-');
+ string str = value.Trim ();
+ str = str.Substring (3).Trim (); // eats "<%#"
+ if (StrUtils.StartsWith (str, "Bind")) {
+ Match match = bindRegex.Match (str);
+ if (match.Success) {
+ string bindingName = match.Groups [1].Value;
+
+ TemplateBuilder templateBuilder = builder.ParentTemplateBuilder;
+ if (templateBuilder == null || templateBuilder.BindingDirection == BindingDirection.OneWay)
+ throw new HttpException ("Bind expression not allowed in this context.");
+
+ string id = builder.attribs ["ID"] as string;
+ if (id == null)
+ throw new HttpException ("Control of type '" + builder.ControlType + "' using two-way binding on property '" + propName + "' must have an ID.");
+
+ templateBuilder.RegisterBoundProperty (builder.ControlType, propName, id, bindingName);
+ value = "<%# Eval" + str.Substring (4);
+ }
+ }
+ }
+#endif
+ /*
+ static bool InvariantCompare (string a, string b)
+ {
+ return (0 == String.Compare (a, b, false, CultureInfo.InvariantCulture));
+ }
+ */
+
+ static bool InvariantCompareNoCase (string a, string b)
+ {
+ return (0 == String.Compare (a, b, true, CultureInfo.InvariantCulture));
+ }
+
+ static MemberInfo GetFieldOrProperty (Type type, string name)
+ {
+ MemberInfo member = null;
+ try {
+ member = type.GetProperty (name, noCaseFlags & ~BindingFlags.NonPublic);
+ } catch {}
+
+ if (member != null)
+ return member;
+
+ try {
+ member = type.GetField (name, noCaseFlags & ~BindingFlags.NonPublic);
+ } catch {}
+
+ return member;
+ }
+
+ bool ProcessPropertiesAndFields (ControlBuilder builder, MemberInfo member, string id,
+ string attValue, string prefix)
+ {
+ int hyphen = id.IndexOf ('-');
bool isPropertyInfo = (member is PropertyInfo);
- bool is_processed = false;
bool isDataBound = IsDataBound (attValue);
Type type;
type = ((FieldInfo) member).FieldType;
}
- if (0 == String.Compare (member.Name, id, true)){
- AddCodeForPropertyOrField (builder, type, member.Name, attValue, isDataBound);
+ if (InvariantCompareNoCase (member.Name, id)) {
+#if NET_2_0
+ if (isDataBound) RegisterBindingInfo (builder, member.Name, ref attValue);
+#endif
+ AddCodeForPropertyOrField (builder, type, member.Name, attValue, member, isDataBound);
return true;
}
string prop_field = id.Replace ("-", ".");
string [] parts = prop_field.Split (new char [] {'.'});
- if (parts.Length != 2 || 0 != String.Compare (member.Name, parts [0], true))
+ int length = parts.Length;
+ if (length < 2 || !InvariantCompareNoCase (member.Name, parts [0]))
return false;
- PropertyInfo [] subprops = type.GetProperties ();
- foreach (PropertyInfo subprop in subprops) {
- if (0 != String.Compare (subprop.Name, parts [1], true))
- continue;
-
- if (subprop.CanWrite == false)
+ if (length > 2) {
+ MemberInfo sub_member = GetFieldOrProperty (type, parts [1]);
+ if (sub_member == null)
return false;
- bool is_bool = subprop.PropertyType == typeof (bool);
- if (!is_bool && attValue == null)
- return false; // Font-Size -> Font-Size="" as html
+ string new_prefix = prefix + parts [0] + ".";
+ string new_id = id.Substring (hyphen + 1);
+ return ProcessPropertiesAndFields (builder, sub_member, new_id, attValue, new_prefix);
+ }
- string value;
- if (attValue == null && is_bool)
- value = "true"; // Font-Bold <=> Font-Bold="true"
- else
- value = attValue;
+ MemberInfo subpf = GetFieldOrProperty (type, parts [1]);
+ if (!(subpf is PropertyInfo))
+ return false;
- AddCodeForPropertyOrField (builder, subprop.PropertyType,
- member.Name + "." + subprop.Name,
- value, isDataBound);
- is_processed = true;
- }
+ PropertyInfo subprop = (PropertyInfo) subpf;
+ if (subprop.CanWrite == false)
+ return false;
+
+ bool is_bool = (subprop.PropertyType == typeof (bool));
+ if (!is_bool && attValue == null)
+ return false; // Font-Size -> Font-Size="" as html
+
+ string val = attValue;
+ if (attValue == null && is_bool)
+ val = "true"; // Font-Bold <=> Font-Bold="true"
+#if NET_2_0
+ if (isDataBound) RegisterBindingInfo (builder, prefix + member.Name + "." + subprop.Name, ref attValue);
+#endif
+ AddCodeForPropertyOrField (builder, subprop.PropertyType,
+ prefix + member.Name + "." + subprop.Name,
+ val, subprop, isDataBound);
- return is_processed;
+ return true;
}
void AddEventAssign (CodeMemberMethod method, string name, Type type, string value)
return;
EventInfo [] ev_info = null;
- PropertyInfo [] prop_info = null;
- FieldInfo [] field_info = null;
bool is_processed = false;
Type type = builder.ControlType;
- foreach (string id in atts.Keys){
- if (0 == String.Compare (id, "runat", true))
+ foreach (string id in atts.Keys) {
+ if (InvariantCompareNoCase (id, "runat"))
continue;
is_processed = false;
string id_as_event = id.Substring (2);
foreach (EventInfo ev in ev_info){
- if (0 == String.Compare (ev.Name, id_as_event, true)){
+ if (InvariantCompareNoCase (ev.Name, id_as_event)){
AddEventAssign (builder.method,
ev.Name,
ev.EventHandlerType,
continue;
}
- if (prop_info == null)
- prop_info = type.GetProperties ();
-
- foreach (PropertyInfo prop in prop_info) {
- is_processed = ProcessPropertiesAndFields (builder, prop, id, attvalue);
- if (is_processed)
- break;
- }
-
- if (is_processed)
- continue;
-
- if (field_info == null)
- field_info = type.GetFields ();
-
- foreach (FieldInfo field in field_info){
- is_processed = ProcessPropertiesAndFields (builder, field, id, attvalue);
+ int hyphen = id.IndexOf ('-');
+ string alt_id = id;
+ if (hyphen != -1)
+ alt_id = id.Substring (0, hyphen);
+
+ MemberInfo fop = GetFieldOrProperty (type, alt_id);
+ if (fop != null) {
+ is_processed = ProcessPropertiesAndFields (builder, fop, id, attvalue, null);
if (is_processed)
- break;
+ continue;
}
if (is_processed)
method.Statements.Add (assign);
}
+#if NET_2_0
+ void AddBindableTemplateInvocation (CodeMemberMethod method, string name, string methodName, string extractMethodName)
+ {
+ CodePropertyReferenceExpression prop = new CodePropertyReferenceExpression (ctrlVar, name);
+
+ CodeObjectCreateExpression newBuild = new CodeObjectCreateExpression (typeof (BuildTemplateMethod));
+ newBuild.Parameters.Add (new CodeMethodReferenceExpression (thisRef, methodName));
+
+ CodeObjectCreateExpression newExtract = new CodeObjectCreateExpression (typeof (ExtractTemplateValuesMethod));
+ newExtract.Parameters.Add (new CodeMethodReferenceExpression (thisRef, extractMethodName));
+
+ CodeObjectCreateExpression newCompiled = new CodeObjectCreateExpression (typeof (CompiledBindableTemplateBuilder));
+ newCompiled.Parameters.Add (newBuild);
+ newCompiled.Parameters.Add (newExtract);
+
+ CodeAssignStatement assign = new CodeAssignStatement (prop, newCompiled);
+ method.Statements.Add (assign);
+ }
+
+ string CreateExtractValuesMethod (TemplateBuilder builder)
+ {
+ CodeMemberMethod method = new CodeMemberMethod ();
+ method.Name = "__ExtractValues_" + builder.ID;
+ method.Attributes = MemberAttributes.Private | MemberAttributes.Final;
+ method.ReturnType = new CodeTypeReference (typeof(IOrderedDictionary));
+
+ CodeParameterDeclarationExpression arg = new CodeParameterDeclarationExpression ();
+ arg.Type = new CodeTypeReference (typeof (Control));
+ arg.Name = "__container";
+ method.Parameters.Add (arg);
+ mainClass.Members.Add (method);
+
+ CodeObjectCreateExpression newTable = new CodeObjectCreateExpression ();
+ newTable.CreateType = new CodeTypeReference (typeof(OrderedDictionary));
+ method.Statements.Add (new CodeVariableDeclarationStatement (typeof(OrderedDictionary), "__table", newTable));
+ CodeVariableReferenceExpression tableExp = new CodeVariableReferenceExpression ("__table");
+
+ if (builder.Bindings != null) {
+ foreach (TemplateBinding binding in builder.Bindings) {
+ CodeVariableDeclarationStatement dec = new CodeVariableDeclarationStatement (binding.ControlType, binding.ControlId);
+ method.Statements.Add (dec);
+ CodeVariableReferenceExpression cter = new CodeVariableReferenceExpression ("__container");
+ CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (cter, "FindControl");
+ invoke.Parameters.Add (new CodePrimitiveExpression (binding.ControlId));
+
+ CodeAssignStatement assign = new CodeAssignStatement ();
+ CodeVariableReferenceExpression control = new CodeVariableReferenceExpression (binding.ControlId);
+ assign.Left = control;
+ assign.Right = new CodeCastExpression (binding.ControlType, invoke);
+ method.Statements.Add (assign);
+
+ CodeConditionStatement sif = new CodeConditionStatement ();
+ sif.Condition = new CodeBinaryOperatorExpression (control, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression (null));
+
+ assign = new CodeAssignStatement ();
+ assign.Left = new CodeIndexerExpression (tableExp, new CodePrimitiveExpression (binding.FieldName));
+ assign.Right = new CodePropertyReferenceExpression (control, binding.ControlProperty);
+ sif.TrueStatements.Add (assign);
+ method.Statements.Add (sif);
+ }
+ }
+
+ method.Statements.Add (new CodeMethodReturnStatement (tableExp));
+ return method.Name;
+ }
+
+ void AddContentTemplateInvocation (ContentControlBuilder cbuilder, CodeMemberMethod method, string methodName)
+ {
+ CodeObjectCreateExpression newBuild = new CodeObjectCreateExpression (typeof (BuildTemplateMethod));
+ newBuild.Parameters.Add (new CodeMethodReferenceExpression (thisRef, methodName));
+
+ CodeObjectCreateExpression newCompiled = new CodeObjectCreateExpression (typeof (CompiledTemplateBuilder));
+ newCompiled.Parameters.Add (newBuild);
+
+ CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (thisRef, "AddContentTemplate");
+ invoke.Parameters.Add (new CodePrimitiveExpression (cbuilder.ContentPlaceHolderID));
+ invoke.Parameters.Add (newCompiled);
+
+ method.Statements.Add (invoke);
+ }
+#endif
+
void AddCodeRender (ControlBuilder parent, CodeRenderBuilder cr)
{
if (cr.Code == null || cr.Code.Trim () == "")
static Type GetContainerType (ControlBuilder builder)
{
- Type type = builder.NamingContainerType;
+ TemplateBuilder tb = builder as TemplateBuilder;
+ if (tb != null && tb.ContainerType != null)
+ return tb.ContainerType;
+
+ Type type = builder.BindingContainerType;
- PropertyInfo prop = type.GetProperty ("Items", noCaseFlags);
+ PropertyInfo prop = type.GetProperty ("Items", noCaseFlags & ~BindingFlags.NonPublic);
if (prop == null)
return type;
if (!typeof (ICollection).IsAssignableFrom (ptype))
return type;
- prop = ptype.GetProperty ("Item", noCaseFlags);
+ prop = ptype.GetProperty ("Item", noCaseFlags & ~BindingFlags.NonPublic);
if (prop == null)
return type;
}
InitMethod (builder, isTemplate, childrenAsProperties);
- if (builder.GetType () != typeof (TemplateBuilder))
+ if (!isTemplate || builder.GetType () == typeof (RootBuilder))
CreateAssignStatementsFromAttributes (builder);
if (builder.Children != null && builder.Children.Count > 0) {
continue;
}
+#if NET_2_0
+ if (b is ContentControlBuilder) {
+ ContentControlBuilder cb = (ContentControlBuilder) b;
+ CreateControlTree (cb, false, true);
+ AddContentTemplateInvocation (cb, builder.method, cb.method.Name);
+ continue;
+ }
+#endif
+
if (b is TemplateBuilder) {
if (templates == null)
templates = new ArrayList ();
AddDataBindingLiteral (builder, (DataBindingBuilder) b);
continue;
}
-
+
if (b is ControlBuilder) {
ControlBuilder child = (ControlBuilder) b;
CreateControlTree (child, inTemplate, builder.ChildrenAsProperties);
FlushText (builder, sb);
if (templates != null) {
- foreach (ControlBuilder b in templates) {
+ foreach (TemplateBuilder b in templates) {
CreateControlTree (b, true, false);
+#if NET_2_0
+ if (b.BindingDirection == BindingDirection.TwoWay) {
+ string extractMethod = CreateExtractValuesMethod (b);
+ AddBindableTemplateInvocation (builder.method, b.TagName, b.method.Name, extractMethod);
+ }
+ else
+#endif
AddTemplateInvocation (builder.method, b.TagName, b.method.Name);
}
}
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);
if (type == typeof (bool)) {
- if (str == null || str == "" || 0 == String.Compare (str, "true", true))
+ if (str == null || str == "" || InvariantCompareNoCase (str, "true"))
return new CodePrimitiveExpression (true);
- else if (0 == String.Compare (str, "false", true))
+ else if (InvariantCompareNoCase (str, "false"))
return new CodePrimitiveExpression (false);
else
throw new ParseException (currentLocation,
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 (',');
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));
+ if (str.Trim().Length == 0) {
+ CodeTypeReferenceExpression ft = new CodeTypeReferenceExpression (typeof (Color));
+ return new CodeFieldReferenceExpression (ft, "Empty");
+ }
+
Color c;
try {
if (str.IndexOf (',') == -1) {
}
}
- TypeConverter converter = TypeDescriptor.GetConverter (type);
+ TypeConverter converter = TypeDescriptor.GetProperties (member.DeclaringType) [member.Name].Converter;
+
if (converter != null && converter.CanConvertFrom (typeof (string))) {
+ object value = converter.ConvertFrom (str);
+
+ if (converter.CanConvertTo (typeof (InstanceDescriptor))) {
+ InstanceDescriptor idesc = (InstanceDescriptor) converter.ConvertTo (value, typeof(InstanceDescriptor));
+ return GenerateInstance (idesc, true);
+ }
+
+ CodeExpression exp = GenerateObjectInstance (value, false);
+ if (exp != null) return exp;
+
CodeMethodReferenceExpression m = new CodeMethodReferenceExpression ();
m.TargetObject = new CodeTypeReferenceExpression (typeof (TypeDescriptor));
m.MethodName = "GetConverter";
return new CodeCastExpression (tref, invoke);
}
+
+ Console.WriteLine ("Unknown type: " + type + " value: " + str);
- bool parms = false;
- BindingFlags flags = BindingFlags.Public | BindingFlags.Static;
- MethodInfo parse = type.GetMethod ("Parse", flags, null, arrayStringCultureInfo, null);
- if (parse != null) {
- parms = true;
- } else {
- parse = type.GetMethod ("Parse", flags, null, arrayString, null);
+ return new CodePrimitiveExpression (str);
+ }
+
+ CodeExpression GenerateInstance (InstanceDescriptor idesc, bool throwOnError)
+ {
+ CodeExpression[] parameters = new CodeExpression [idesc.Arguments.Count];
+ int n = 0;
+ foreach (object ob in idesc.Arguments) {
+ CodeExpression exp = GenerateObjectInstance (ob, throwOnError);
+ if (exp == null) return null;
+ parameters [n++] = exp;
}
-
- 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);
- }
+
+ 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, bool throwOnError)
+ {
+ if (value == null)
+ return new CodePrimitiveExpression (null);
+
+ Type t = value.GetType();
+ if (t.IsPrimitive || value is string)
+ return new CodePrimitiveExpression (value);
- 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);
+ if (t.IsArray) {
+ Array ar = (Array) value;
+ CodeExpression[] items = new CodeExpression [ar.Length];
+ for (int n=0; n<ar.Length; n++) {
+ CodeExpression exp = GenerateObjectInstance (ar.GetValue (n), throwOnError);
+ if (exp == null) return null;
+ items [n] = exp;
}
- return invoke;
+ return new CodeArrayCreateExpression (new CodeTypeReference (t), items);
}
-
- // FIXME: Arrays
- Console.WriteLine ("Unknown type: " + type + " value: " + str);
-
- return new CodePrimitiveExpression (str);
+
+ TypeConverter converter = TypeDescriptor.GetConverter (t);
+ if (converter != null && converter.CanConvertTo (typeof (InstanceDescriptor))) {
+ InstanceDescriptor idesc = (InstanceDescriptor) converter.ConvertTo (value, typeof(InstanceDescriptor));
+ return GenerateInstance (idesc, throwOnError);
+ }
+
+ InstanceDescriptor desc = GetDefaultInstanceDescriptor (value);
+ if (desc != null) return GenerateInstance (desc, throwOnError);
+
+ if (throwOnError)
+ throw new ParseException (currentLocation, "Cannot generate an instance for the type: " + t);
+ else
+ return null;
+ }
+
+ 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;
}
}
}