System.Web.Compilation.TemplateControlCompiler.GetExpressionFromString C# (CSharp) Method

GetExpressionFromString() private method

private GetExpressionFromString ( Type type, string str, MemberInfo member ) : System.CodeDom.CodeExpression
type System.Type
str string
member System.Reflection.MemberInfo
return System.CodeDom.CodeExpression
		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 (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;
			}

			if (type == typeof (string)) {
				object[] urlAttr = member.GetCustomAttributes (typeof (UrlPropertyAttribute), true);
				if (urlAttr.Length != 0)
					str = HandleUrlProperty ((preConverted && convertedFromAttr is string) ? (string)convertedFromAttr : str, member);
				else if (preConverted)
					return CreateNullableExpression (originalType,
									 new CodePrimitiveExpression ((string) convertedFromAttr),
									 wasNullable);

				return CreateNullableExpression (originalType, new CodePrimitiveExpression (str), wasNullable);
			} else if (type == typeof (bool)) {
				if (preConverted)
					return CreateNullableExpression (originalType,
									 new CodePrimitiveExpression ((bool) convertedFromAttr),
									 wasNullable);
				
				if (str == null || str == "" || InvariantCompareNoCase (str, "true"))
					return CreateNullableExpression (originalType, new CodePrimitiveExpression (true), wasNullable);
				else if (InvariantCompareNoCase (str, "false"))
					return CreateNullableExpression (originalType, new CodePrimitiveExpression (false), wasNullable);
				else if (wasNullable && InvariantCompareNoCase(str, "null"))
					return new CodePrimitiveExpression (null);
				else
					throw new ParseException (currentLocation,
							"Value '" + str  + "' is not a valid boolean.");
			} else if (type == monoTypeType)
				type = typeof (System.Type);
			
			if (str == null)
				return new CodePrimitiveExpression (null);

			if (type.IsPrimitive)
				return CreateNullableExpression (originalType,
								 new CodePrimitiveExpression (
									 Convert.ChangeType (preConverted ? convertedFromAttr : str,
											     type, Helpers.InvariantCulture)),
								 wasNullable);

			if (type == typeof (string [])) {
				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)
					expr.Initializers.Add (new CodePrimitiveExpression (v.Trim ()));

				return CreateNullableExpression (originalType, expr, wasNullable);
			}
			
			if (type == typeof (Color)) {
				Color c;
				
				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);
					}

					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 CreateNullableExpression (originalType, expr, wasNullable);
				} else {
					CodeMethodReferenceExpression m = new CodeMethodReferenceExpression ();
					m.TargetObject = new CodeTypeReferenceExpression (type);
					m.MethodName = "FromArgb";
					CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (m);
					invoke.Parameters.Add (new CodePrimitiveExpression (c.A));
					invoke.Parameters.Add (new CodePrimitiveExpression (c.R));
					invoke.Parameters.Add (new CodePrimitiveExpression (c.G));
					invoke.Parameters.Add (new CodePrimitiveExpression (c.B));
					return CreateNullableExpression (originalType, invoke, wasNullable);
				}
			}

			TypeConverter converter = preConverted ? cvt : wasNullable ? TypeDescriptor.GetConverter (type) : null;
			if (converter == null) {
				PropertyDescriptor pdesc = TypeDescriptor.GetProperties (member.DeclaringType) [member.Name];
				if (pdesc != null)
					converter = pdesc.Converter;
				else {
					Type memberType;
					switch (member.MemberType) {
						case MemberTypes.Field:
							memberType = ((FieldInfo)member).FieldType;
							break;

						case MemberTypes.Property:
							memberType = ((PropertyInfo)member).PropertyType;
							break;

						default:
							memberType = null;
							break;
					}

					if (memberType == null)
						return null;

					converter = TypeDescriptor.GetConverter (memberType);
				}
			}
			
			if (preConverted || (converter != null && SafeCanConvertFrom (typeof (string), converter))) {
				object value = preConverted ? convertedFromAttr : converter.ConvertFromInvariantString (str);

				if (SafeCanConvertTo (typeof (InstanceDescriptor), converter)) {
					InstanceDescriptor idesc = (InstanceDescriptor) converter.ConvertTo (value, typeof(InstanceDescriptor));
					if (wasNullable)
						return CreateNullableExpression (originalType, GenerateInstance (idesc, true),
										 wasNullable);

					CodeExpression instance = GenerateInstance (idesc, true);
					if (type.IsPublic)
						return new CodeCastExpression (type, instance);
					else
						return instance;
				}

				CodeExpression exp = GenerateObjectInstance (value, false);
				if (exp != null)
					return CreateNullableExpression (originalType, exp, wasNullable);
				
				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));

				if (wasNullable)
					return CreateNullableExpression (originalType, invoke, wasNullable);

				return new CodeCastExpression (type, invoke);
			}

			Console.WriteLine ("Unknown type: " + type + " value: " + str);
			
			return CreateNullableExpression (originalType, new CodePrimitiveExpression (str), wasNullable);
		}
		
TemplateControlCompiler