}
void AddCodeForPropertyOrField (ControlBuilder builder, Type type, string var_name, string att, MemberInfo member, bool isDataBound, bool isExpression)
- {
+ {
CodeMemberMethod method = builder.method;
bool isWritable = IsWritablePropertyOrField (member);
if (isDataBound && isWritable) {
Type t;
try {
- t = System.Type.GetType (builderType, true);
+ t = HttpApplication.LoadType (builderType, true);
} catch (Exception e) {
throw new HttpException (
String.Format ("Failed to load expression builder type `{0}'", builderType), e);
if (StrUtils.StartsWith (inputFile, physPath))
inputFile = parser.InputFile.Substring (physPath.Length - 1);
- else
+ else
return;
-
+
+ char dsc = System.IO.Path.DirectorySeparatorChar;
+ if (dsc != '/')
+ inputFile = inputFile.Replace (dsc, '/');
+
object obj = HttpContext.GetLocalResourceObject (inputFile, resname);
if (obj == null)
return;
bool doCheck = false;
#if NET_2_0
- TemplateBuilder pb = builder.parentBuilder as TemplateBuilder;
- if (pb == null || pb.TemplateInstance != TemplateInstance.Single)
+ bool singleInstance = false;
+ ControlBuilder pb = builder.parentBuilder;
+ TemplateBuilder tpb;
+ while (pb != null) {
+ tpb = pb as TemplateBuilder;
+ if (tpb == null) {
+ pb = pb.parentBuilder;
+ continue;
+ }
+
+ if (tpb.TemplateInstance == TemplateInstance.Single)
+ singleInstance = true;
+ break;
+ }
+
+ if (!singleInstance)
#endif
builder.ID = builder.GetNextID (null);
#if NET_2_0
return str;
}
#endif
-
- CodeExpression GetExpressionFromString (Type type, string str, MemberInfo member)
- {
+
+ TypeConverter GetConverterForMember (MemberInfo member)
+ {
+ TypeConverterAttribute tca = null;
+ object[] attrs;
+
#if NET_2_0
- bool wasNullable = false;
+ attrs = member.GetCustomAttributes (typeof (TypeConverterAttribute), true);
+ if (attrs.Length > 0)
+ tca = attrs [0] as TypeConverterAttribute;
+#else
+ attrs = member.GetCustomAttributes (true);
+ foreach (object attr in attrs) {
+ tca = attr as TypeConverterAttribute;
+
+ if (tca != null)
+ break;
+ }
+#endif
+
+ if (tca == null)
+ return null;
+
+ string typeName = tca.ConverterTypeName;
+ if (typeName == null || typeName.Length == 0)
+ return null;
+
+ Type t = null;
+ try {
+ t = HttpApplication.LoadType (typeName);
+ } catch (Exception) {
+ // ignore
+ }
+
+ if (t == null)
+ return null;
+
+ return (TypeConverter) Activator.CreateInstance (t);
+ }
+
+ CodeExpression CreateNullableExpression (Type type, CodeExpression inst, bool nullable)
+ {
+#if NET_2_0
+ if (!nullable)
+ return inst;
+
+ return new CodeObjectCreateExpression (
+ type,
+ new CodeExpression[] {inst}
+ );
+#else
+ return inst;
+#endif
+ }
+
+ bool SafeCanConvertFrom (Type type, TypeConverter cvt)
+ {
+ try {
+ return cvt.CanConvertFrom (type);
+ } catch (NotImplementedException) {
+ return false;
+ }
+ }
+
+ bool SafeCanConvertTo (Type type, TypeConverter cvt)
+ {
+ try {
+ return cvt.CanConvertTo (type);
+ } catch (NotImplementedException) {
+ return false;
+ }
+ }
+
+ CodeExpression GetExpressionFromString (Type type, string str, MemberInfo member)
+ {
+ TypeConverter cvt = GetConverterForMember (member);
+ if (cvt != null && !SafeCanConvertFrom (typeof (string), cvt))
+ cvt = null;
+
+ object convertedFromAttr = null;
+ bool preConverted = false;
+ if (cvt != null && str != null) {
+ convertedFromAttr = cvt.ConvertFromInvariantString (str);
+ if (convertedFromAttr != null) {
+ type = convertedFromAttr.GetType ();
+ preConverted = true;
+ }
+ }
+
+ bool wasNullable = false;
+ Type originalType = type;
+#if NET_2_0
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) {
Type[] types = type.GetGenericArguments();
+ originalType = type;
type = types[0]; // we're interested only in the first type here
wasNullable = true;
}
#endif
-
+
if (type == typeof (string)) {
+ if (preConverted)
+ return CreateNullableExpression (originalType,
+ new CodePrimitiveExpression ((string) convertedFromAttr),
+ wasNullable);
+
#if NET_2_0
object[] urlAttr = member.GetCustomAttributes (typeof (UrlPropertyAttribute), true);
if (urlAttr.Length != 0)
str = HandleUrlProperty (str, member);
#endif
- return new CodePrimitiveExpression (str);
+ return CreateNullableExpression (originalType, new CodePrimitiveExpression (str), wasNullable);
}
if (type == typeof (bool)) {
+ if (preConverted)
+ return CreateNullableExpression (originalType,
+ new CodePrimitiveExpression ((bool) convertedFromAttr),
+ wasNullable);
+
if (str == null || str == "" || InvariantCompareNoCase (str, "true"))
- return new CodePrimitiveExpression (true);
+ return CreateNullableExpression (originalType, new CodePrimitiveExpression (true), wasNullable);
else if (InvariantCompareNoCase (str, "false"))
- return new CodePrimitiveExpression (false);
+ return CreateNullableExpression (originalType, new CodePrimitiveExpression (false), wasNullable);
#if NET_2_0
else if (wasNullable && InvariantCompareNoCase(str, "null"))
return new CodePrimitiveExpression (null);
throw new ParseException (currentLocation,
"Value '" + str + "' is not a valid boolean.");
}
-
+
if (str == null)
return new CodePrimitiveExpression (null);
if (type.IsPrimitive)
- return new CodePrimitiveExpression (Convert.ChangeType (str, type, CultureInfo.InvariantCulture));
+ return CreateNullableExpression (originalType,
+ new CodePrimitiveExpression (
+ Convert.ChangeType (preConverted ? convertedFromAttr : str,
+ type, CultureInfo.InvariantCulture)),
+ wasNullable);
if (type == typeof (string [])) {
- string [] subs = str.Split (',');
+ string [] subs;
+
+ if (preConverted)
+ subs = (string[])convertedFromAttr;
+ else
+ subs = str.Split (',');
CodeArrayCreateExpression expr = new CodeArrayCreateExpression ();
expr.CreateType = new CodeTypeReference (typeof (string));
- foreach (string v in subs) {
+ foreach (string v in subs)
expr.Initializers.Add (new CodePrimitiveExpression (v.Trim ()));
- }
- return expr;
+ return CreateNullableExpression (originalType, expr, wasNullable);
}
-
- 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");
- }
-
+
+ if (type == typeof (Color)) {
Color c;
- try {
- if (str.IndexOf (',') == -1) {
- c = (Color) colorConverter.ConvertFromString (str);
- } else {
- int [] argb = new int [4];
- argb [0] = 255;
-
- string [] parts = str.Split (',');
- int length = parts.Length;
- if (length < 3)
- throw new Exception ();
-
- int basei = (length == 4) ? 0 : 1;
- for (int i = length - 1; i >= 0; i--) {
- argb [basei + i] = (int) Byte.Parse (parts [i]);
- }
- c = Color.FromArgb (argb [0], argb [1], argb [2], argb [3]);
- }
- } catch (Exception e){
- // Hack: "LightGrey" is accepted, but only for ASP.NET, as the
- // TypeConverter for Color fails to ConvertFromString.
- // Hence this hack...
- if (InvariantCompareNoCase ("LightGrey", str)) {
- c = Color.LightGray;
- } else {
- throw new ParseException (currentLocation,
- "Color " + str + " is not a valid color.", e);
+
+ if (!preConverted) {
+ if (colorConverter == null)
+ colorConverter = TypeDescriptor.GetConverter (typeof (Color));
+
+ if (str.Trim().Length == 0) {
+ CodeTypeReferenceExpression ft = new CodeTypeReferenceExpression (typeof (Color));
+ return CreateNullableExpression (originalType,
+ new CodeFieldReferenceExpression (ft, "Empty"),
+ wasNullable);
}
- }
- if (c.IsKnownColor){
+ try {
+ if (str.IndexOf (',') == -1) {
+ c = (Color) colorConverter.ConvertFromString (str);
+ } else {
+ int [] argb = new int [4];
+ argb [0] = 255;
+
+ string [] parts = str.Split (',');
+ int length = parts.Length;
+ if (length < 3)
+ throw new Exception ();
+
+ int basei = (length == 4) ? 0 : 1;
+ for (int i = length - 1; i >= 0; i--) {
+ argb [basei + i] = (int) Byte.Parse (parts [i]);
+ }
+ c = Color.FromArgb (argb [0], argb [1], argb [2], argb [3]);
+ }
+ } catch (Exception e) {
+ // Hack: "LightGrey" is accepted, but only for ASP.NET, as the
+ // TypeConverter for Color fails to ConvertFromString.
+ // Hence this hack...
+ if (InvariantCompareNoCase ("LightGrey", str)) {
+ c = Color.LightGray;
+ } else {
+ throw new ParseException (currentLocation,
+ "Color " + str + " is not a valid color.", e);
+ }
+ }
+ } else
+ c = (Color)convertedFromAttr;
+
+ if (c.IsKnownColor) {
CodeFieldReferenceExpression expr = new CodeFieldReferenceExpression ();
if (c.IsSystemColor)
type = typeof (SystemColors);
expr.TargetObject = new CodeTypeReferenceExpression (type);
expr.FieldName = c.Name;
- return expr;
+ return CreateNullableExpression (originalType, expr, wasNullable);
} else {
CodeMethodReferenceExpression m = new CodeMethodReferenceExpression ();
m.TargetObject = new CodeTypeReferenceExpression (type);
invoke.Parameters.Add (new CodePrimitiveExpression (c.R));
invoke.Parameters.Add (new CodePrimitiveExpression (c.G));
invoke.Parameters.Add (new CodePrimitiveExpression (c.B));
- return invoke;
+ return CreateNullableExpression (originalType, invoke, wasNullable);
}
}
- TypeConverter converter = TypeDescriptor.GetProperties (member.DeclaringType) [member.Name].Converter;
-
- if (converter != null && converter.CanConvertFrom (typeof (string))) {
- object value = converter.ConvertFromInvariantString (str);
+ TypeConverter converter = preConverted ? cvt :
+ wasNullable ? TypeDescriptor.GetConverter (type) :
+ TypeDescriptor.GetProperties (member.DeclaringType) [member.Name].Converter;
+
+ if (preConverted || (converter != null && SafeCanConvertFrom (typeof (string), converter))) {
+ object value = preConverted ? convertedFromAttr : converter.ConvertFromInvariantString (str);
- if (converter.CanConvertTo (typeof (InstanceDescriptor))) {
+ if (SafeCanConvertTo (typeof (InstanceDescriptor), converter)) {
InstanceDescriptor idesc = (InstanceDescriptor) converter.ConvertTo (value, typeof(InstanceDescriptor));
- return GenerateInstance (idesc, true);
+ if (wasNullable)
+ return CreateNullableExpression (originalType, GenerateInstance (idesc, true),
+ wasNullable);
+
+ return new CodeCastExpression (type, GenerateInstance (idesc, true));
}
CodeExpression exp = GenerateObjectInstance (value, false);
- if (exp != null) return exp;
+ if (exp != null)
+ return CreateNullableExpression (originalType, exp, wasNullable);
CodeMethodReferenceExpression m = new CodeMethodReferenceExpression ();
m.TargetObject = new CodeTypeReferenceExpression (typeof (TypeDescriptor));
invoke = new CodeMethodInvokeExpression (invoke, "ConvertFrom");
invoke.Parameters.Add (new CodePrimitiveExpression (str));
- return new CodeCastExpression (tref, invoke);
+ if (wasNullable)
+ return CreateNullableExpression (originalType, invoke, wasNullable);
+
+ return new CodeCastExpression (type, invoke);
}
Console.WriteLine ("Unknown type: " + type + " value: " + str);
-
- return new CodePrimitiveExpression (str);
+
+ return CreateNullableExpression (originalType, new CodePrimitiveExpression (str), wasNullable);
}
CodeExpression GenerateInstance (InstanceDescriptor idesc, bool throwOnError)
{
if (value == null)
return new CodePrimitiveExpression (null);
+
+ if (value is System.Type) {
+ CodeTypeReference tref = new CodeTypeReference (value.ToString ());
+ return new CodeTypeOfExpression (tref);
+ }
- Type t = value.GetType();
+ 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];