#if NET_2_0
using System.Configuration;
using System.Collections.Specialized;
+using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Web.Configuration;
#endif
internal static CodeVariableReferenceExpression ctrlVar = new CodeVariableReferenceExpression ("__ctrl");
#if NET_2_0
- static Regex bindRegex = new Regex (@"Bind\s*\(""(.*?)""\)\s*%>", RegexOptions.Compiled);
+ static Regex bindRegex = new Regex (@"Bind\s*\(""(.*?)""\)\s*%>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
+ static Regex bindRegexInValue = new Regex (@"Bind\s*\(""(.*?)""\)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
#endif
public TemplateControlCompiler (TemplateControlParser parser)
}
void CreateField (ControlBuilder builder, bool check)
- {
+ {
+ if (builder == null || builder.ID == null || builder.ControlType == null)
+ return;
#if NET_2_0
if (partialNameOverride [builder.ID] != null)
return;
#endif
+
+ MemberAttributes ma = MemberAttributes.Family;
currentLocation = builder.location;
- if (check && CheckBaseFieldOrProperty (builder.ID, builder.ControlType))
+ if (check && CheckBaseFieldOrProperty (builder.ID, builder.ControlType, ref ma))
return; // The field or property already exists in a base class and is accesible.
CodeMemberField field;
field = new CodeMemberField (builder.ControlType.FullName, builder.ID);
- field.Attributes = MemberAttributes.Family;
- mainClass.Members.Add (field);
+ field.Attributes = ma;
+#if NET_2_0
+ field.Type.Options |= CodeTypeReferenceOptions.GlobalReference;
+
+ if (partialClass != null)
+ partialClass.Members.Add (field);
+ else
+#endif
+ mainClass.Members.Add (field);
}
- bool CheckBaseFieldOrProperty (string id, Type type)
+ bool CheckBaseFieldOrProperty (string id, Type type, ref MemberAttributes ma)
{
FieldInfo fld = parser.BaseType.GetField (id, noCaseFlags);
return false;
if (!other.IsAssignableFrom (type)) {
+#if NET_2_0
+ ma |= MemberAttributes.New;
+ return false;
+#else
string msg = String.Format ("The base class includes the field '{0}', but its " +
"type '{1}' is not compatible with {2}",
id, other, type);
throw new ParseException (currentLocation, msg);
+#endif
}
return true;
/* in the case this is the __BuildControlTree
* method, allow subclasses to insert control
* specific code. */
- if (builder is RootBuilder)
+ if (builder is RootBuilder) {
+#if NET_2_0
+ SetCustomAttributes (method);
+#endif
AddStatementsToInitMethod (method);
-
+ }
+
if (builder.HasAspCode) {
CodeMemberMethod renderMethod = new CodeMemberMethod ();
builder.renderMethod = renderMethod;
if (childrenAsProperties || builder.ControlType == null) {
string typeString;
- if (builder is RootBuilder) {
-#if NET_2_0
- if (parser.IsPartial)
- typeString = parser.PartialClassName;
- else
-#endif
- typeString = parser.ClassName;
- }
+ if (builder is RootBuilder)
+ typeString = parser.ClassName;
else {
if (builder.ControlType != null && builder.isProperty &&
!typeof (ITemplate).IsAssignableFrom (builder.ControlType))
}
#if NET_2_0
+ if (builder.ParentTemplateBuilder is System.Web.UI.WebControls.ContentBuilderInternal) {
+ PropertyInfo pi;
+
+ try {
+ pi = type.GetProperty ("TemplateControl");
+ } catch (Exception) {
+ pi = null;
+ }
+
+ if (pi != null && pi.CanWrite) {
+ // __ctrl.TemplateControl = this;
+ assign = new CodeAssignStatement ();
+ assign.Left = new CodePropertyReferenceExpression (ctrlVar, "TemplateControl");;
+ assign.Right = thisRef;
+ method.Statements.Add (assign);
+ }
+ }
+
// _ctrl.SkinID = $value
// _ctrl.ApplyStyleSheetSkin (this);
//
}
#endif
+ // process ID here. It should be set before any other attributes are
+ // assigned, since the control code may rely on ID being set. We
+ // skip ID in CreateAssignStatementsFromAttributes
+ if (builder.attribs != null) {
+ string ctl_id = builder.attribs ["id"] as string;
+ if (ctl_id != null && ctl_id != String.Empty)
+ CreateAssignStatementFromAttribute (builder, "id");
+ }
#if NET_2_0
if (typeof (ContentPlaceHolder).IsAssignableFrom (type)) {
CodePropertyReferenceExpression prop = new CodePropertyReferenceExpression (thisRef, "ContentPlaceHolders");
// this is the bit that causes the following stuff to end up in the else { }
builder.methodStatements = condStatement.FalseStatements;
-
- // __ctrl.TemplateControl = this;
- assign = new CodeAssignStatement ();
- assign.Left = new CodePropertyReferenceExpression (ctrlVar, "TemplateControl");;
- assign.Right = thisRef;
-
- method.Statements.Add (assign);
}
#endif
}
-
+
mainClass.Members.Add (method);
}
+#if NET_2_0
+ void SetCustomAttribute (CodeMemberMethod method, UnknownAttributeDescriptor uad)
+ {
+ CodeAssignStatement assign = new CodeAssignStatement ();
+ assign.Left = new CodePropertyReferenceExpression (
+ new CodeArgumentReferenceExpression("__ctrl"),
+ uad.Info.Name);
+ assign.Right = GetExpressionFromString (uad.Value.GetType (), uad.Value.ToString (), uad.Info);
+
+ method.Statements.Add (assign);
+ }
+
+ void SetCustomAttributes (CodeMemberMethod method)
+ {
+ Type baseType = parser.BaseType;
+ if (baseType == null)
+ return;
+
+ List <UnknownAttributeDescriptor> attrs = parser.UnknownMainAttributes;
+ if (attrs == null || attrs.Count == 0)
+ return;
+
+ foreach (UnknownAttributeDescriptor uad in attrs)
+ SetCustomAttribute (method, uad);
+ }
+#endif
+
protected virtual void AddStatementsToInitMethod (CodeMemberMethod method)
{
}
#if NET_2_0
bool need_if = false;
value = value.Trim ();
- if (StrUtils.StartsWith (value, "Bind")) {
- value = "Eval" + value.Substring (4);
- need_if = true;
+ if (StrUtils.StartsWith (value, "Bind", true)) {
+ Match match = bindRegexInValue.Match (value);
+ if (match.Success) {
+ value = "Eval" + value.Substring (4);
+ need_if = true;
+ }
}
#endif
-
method = CreateDBMethod (dbMethodName, GetContainerType (builder), builder.ControlType);
-
+
CodeVariableReferenceExpression targetExpr = new CodeVariableReferenceExpression ("target");
// This should be a CodePropertyReferenceExpression for properties... but it works anyway
CodeAssignStatement assign = new CodeAssignStatement (field, expr);
#if NET_2_0
if (need_if) {
- CodeExpression page = new CodePropertyReferenceExpression (new CodeThisReferenceExpression (), "Page");
+ CodeExpression page = new CodePropertyReferenceExpression (thisRef, "Page");
CodeExpression left = new CodeMethodInvokeExpression (page, "GetDataItem");
CodeBinaryOperatorExpression ce = new CodeBinaryOperatorExpression (left, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression (null));
CodeConditionStatement ccs = new CodeConditionStatement (ce, assign);
}
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) {
{
string str = value.Trim ();
str = str.Substring (3).Trim (); // eats "<%#"
- if (StrUtils.StartsWith (str, "Bind")) {
+ if (StrUtils.StartsWith (str, "Bind", true)) {
Match match = bindRegex.Match (str);
if (match.Success) {
string bindingName = match.Groups [1].Value;
string prop_field = id.Replace ("-", ".");
string [] parts = prop_field.Split (new char [] {'.'});
int length = parts.Length;
+
if (length < 2 || !InvariantCompareNoCase (member.Name, parts [0]))
return false;
if (sub_member == null)
return false;
- string new_prefix = prefix + parts [0] + ".";
+ string new_prefix = prefix + member.Name + ".";
string new_id = id.Substring (hyphen + 1);
return ProcessPropertiesAndFields (builder, sub_member, new_id, attValue, new_prefix);
}
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);
builderType));
System.Web.Compilation.ExpressionBuilder eb = null;
- ResourceExpressionFields fields;
+ object parsedData;
ExpressionBuilderContext ctx;
try {
eb = Activator.CreateInstance (t) as System.Web.Compilation.ExpressionBuilder;
ctx = new ExpressionBuilderContext (HttpContext.Current.Request.FilePath);
- fields = eb.ParseExpression (expr.Substring (colon + 1).Trim (),
- type,
- ctx) as ResourceExpressionFields;
+ parsedData = eb.ParseExpression (expr.Substring (colon + 1).Trim (), type, ctx);
} catch (Exception e) {
throw new HttpException (
String.Format ("Failed to create an instance of type `{0}'", builderType), e);
}
- // FIXME: create and pass an instance of BoundPropertyEntry
- CodeMethodInvokeExpression convert = new CodeMethodInvokeExpression ();
- convert.Method = new CodeMethodReferenceExpression (
- new CodeTypeReferenceExpression (typeof(Convert)),
- "ToString");
- convert.Parameters.Add (eb.GetCodeExpression (null, fields, ctx));
- convert.Parameters.Add (
- new CodePropertyReferenceExpression (
- new CodeTypeReferenceExpression (typeof(Globalization.CultureInfo)),
- "CurrentCulture"));
- assign.Right = convert;
+ BoundPropertyEntry bpe = CreateBoundPropertyEntry (member as PropertyInfo, prefix, expr);
+ assign.Right = eb.GetCodeExpression (bpe, parsedData, ctx);
method.Statements.Add (assign);
}
- void AssignPropertyFromResources (CodeMemberMethod method, MemberInfo mi, string attvalue, string varname)
+ BoundPropertyEntry CreateBoundPropertyEntry (PropertyInfo pi, string prefix, string expr)
+ {
+ if (pi == null)
+ return null;
+
+ BoundPropertyEntry ret = new BoundPropertyEntry ();
+ ret.Expression = expr;
+ ret.ExpressionPrefix = prefix;
+ ret.Generated = false;
+ ret.Name = pi.Name;
+ ret.PropertyInfo = pi;
+ ret.Type = pi.PropertyType;
+
+ return ret;
+ }
+
+ void AssignPropertyFromResources (CodeMemberMethod method, MemberInfo mi, string attvalue)
{
- string resname = String.Format ("{0}.{1}", attvalue, mi.Name);
bool isProperty = mi.MemberType == MemberTypes.Property;
bool isField = !isProperty && (mi.MemberType == MemberTypes.Field);
if (!isProperty && !isField || !IsWritablePropertyOrField (mi))
- return;
-
- Type member_type = null;
- if (isProperty) {
- PropertyInfo pi = mi as PropertyInfo;
- member_type = pi.PropertyType;
- } else if (isField) {
- FieldInfo fi = mi as FieldInfo;
- member_type = fi.FieldType;
- } else // should never happen
+ return;
+
+ string memberName = mi.Name;
+ string resname = String.Format ("{0}.{1}", attvalue, memberName);
+
+ // __ctrl.Text = System.Convert.ToString(HttpContext.GetLocalResourceObject("ButtonResource1.Text"));
+ string inputFile = parser.InputFile;
+ string physPath = HttpContext.Current.Request.PhysicalApplicationPath;
+
+ if (StrUtils.StartsWith (inputFile, physPath))
+ inputFile = parser.InputFile.Substring (physPath.Length - 1);
+ else
return;
- // __ctrl.Text = System.Convert.ToString(this.GetLocalResourceObject("ButtonResource1.Text"), System.Globalization.CultureInfo.CurrentCulture);
- object obj = HttpContext.GetLocalResourceObject (HttpContext.Current.Request.FilePath,
- resname);
+ char dsc = System.IO.Path.DirectorySeparatorChar;
+ if (dsc != '/')
+ inputFile = inputFile.Replace (dsc, '/');
+
+ object obj = HttpContext.GetLocalResourceObject (inputFile, resname);
if (obj == null)
return;
+
+ if (!isProperty && !isField)
+ return; // an "impossible" case
+ Type declaringType = mi.DeclaringType;
CodeAssignStatement assign = new CodeAssignStatement ();
- assign.Left = new CodePropertyReferenceExpression (ctrlVar, mi.Name);
- CodeMethodInvokeExpression getlro = new CodeMethodInvokeExpression (
- new CodeThisReferenceExpression (),
- "GetLocalResourceObject",
- new CodeExpression [] { new CodePrimitiveExpression (resname) });
- CodeMethodInvokeExpression convert = new CodeMethodInvokeExpression ();
- convert.Method = new CodeMethodReferenceExpression (
- new CodeTypeReferenceExpression (typeof(System.Convert)),
- "ToString");
- convert.Parameters.Add (getlro);
- convert.Parameters.Add (
- new CodePropertyReferenceExpression (
- new CodeTypeReferenceExpression (typeof(Globalization.CultureInfo)),
- "CurrentCulture"));
- assign.Right = convert;
+ assign.Left = new CodePropertyReferenceExpression (ctrlVar, memberName);
+ assign.Right = ResourceExpressionBuilder.CreateGetLocalResourceObject (mi, resname);
-// assign.Left = new CodeVariableReferenceExpression (varname);
-// assign.Right = new CodeMethodInvokeExpression (
-// new CodeThisReferenceExpression (),
-// "GetLocalResourceObject",
-// new CodeExpression [] { new CodePrimitiveExpression (resname) });
-// method.Statements.Add (assign);
-
-// // if (localResourceObject != null && localResourceObject.GetType() == typeof(member_type))
-// CodeConditionStatement ccs = new CodeConditionStatement ();
-// CodeBinaryOperatorExpression exp1 = new CodeBinaryOperatorExpression (
-// new CodeVariableReferenceExpression (varname),
-// CodeBinaryOperatorType.IdentityInequality,
-// new CodePrimitiveExpression (null));
-
-// CodeBinaryOperatorExpression exp2 = new CodeBinaryOperatorExpression (
-// new CodeMethodInvokeExpression (
-// new CodeVariableReferenceExpression (varname),
-// "GetType",
-// new CodeExpression [] {}),
-// CodeBinaryOperatorType.IdentityEquality,
-// new CodeTypeOfExpression (
-// new CodeTypeReference (member_type.ToString ())));
-// ccs.Condition = new CodeBinaryOperatorExpression (
-// exp1,
-// CodeBinaryOperatorType.BooleanAnd,
-// exp2);
-
-// // ctrlVar.Property = (member_type)obj;
-// assign = new CodeAssignStatement ();
-// assign.Left = new CodePropertyReferenceExpression (ctrlVar, mi.Name);
-// assign.Right = new CodeCastExpression (
-// member_type.ToString (),
-// new CodeVariableReferenceExpression (varname));
-// ccs.TrueStatements.Add (assign);
method.Statements.Add (assign);
}
-
- void AssignPropertiesFromResources (ControlBuilder builder, string attvalue)
- {
- if (attvalue == null || attvalue.Length == 0)
- return;
-
- Type controlType = builder.ControlType;
- if (controlType == null)
- return;
- // object obj = null;
-
+ void AssignPropertiesFromResources (CodeMemberMethod method, Type controlType, string attvalue)
+ {
// Process all public fields and properties of the control. We don't use GetMembers to make the code
// faster
FieldInfo [] fields = controlType.GetFields (
BindingFlags.Instance | BindingFlags.Static |
BindingFlags.Public | BindingFlags.FlattenHierarchy);
- if (fields.Length > 0 || properties.Length > 0) {
- CodeVariableDeclarationStatement cvds = new CodeVariableDeclarationStatement (
- typeof (object),
- "localResourceObject",
- new CodePrimitiveExpression (null));
- builder.method.Statements.Add (cvds);
- }
-
foreach (FieldInfo fi in fields)
- AssignPropertyFromResources (builder.method, fi, attvalue, "localResourceObject");
+ AssignPropertyFromResources (method, fi, attvalue);
foreach (PropertyInfo pi in properties)
- AssignPropertyFromResources (builder.method, pi, attvalue, "localResourceObject");
+ AssignPropertyFromResources (method, pi, attvalue);
+ }
+
+ void AssignPropertiesFromResources (ControlBuilder builder, string attvalue)
+ {
+ if (attvalue == null || attvalue.Length == 0)
+ return;
+
+ Type controlType = builder.ControlType;
+ if (controlType == null)
+ return;
+
+ AssignPropertiesFromResources (builder.method, controlType, attvalue);
}
#endif
{
EventInfo [] ev_info = null;
Type type = builder.ControlType;
-
+
string attvalue = builder.attribs [id] as string;
if (id.Length > 2 && id.Substring (0, 2).ToUpper () == "ON"){
if (ev_info == null)
protected void CreateAssignStatementsFromAttributes (ControlBuilder builder)
{
+#if NET_2_0
+ bool haveMetaKey = false;
+#endif
this.dataBoundAtts = 0;
IDictionary atts = builder.attribs;
if (atts == null || atts.Count == 0)
return;
-
+
foreach (string id in atts.Keys) {
if (InvariantCompareNoCase (id, "runat"))
continue;
-
+ // ID is assigned in BuildControltree
+ if (InvariantCompareNoCase (id, "id"))
+ continue;
+
#if NET_2_0
/* we skip SkinID here as it's assigned in BuildControlTree */
if (InvariantCompareNoCase (id, "skinid"))
continue;
+ if (InvariantCompareNoCase (id, "meta:resourcekey")) {
+ haveMetaKey = true;
+ continue;
+ }
#endif
CreateAssignStatementFromAttribute (builder, id);
}
+
+#if NET_2_0
+ if (haveMetaKey)
+ CreateAssignStatementFromAttribute (builder, "meta:resourcekey");
+#endif
}
void CreateDBAttributeMethod (ControlBuilder builder, string attr, string code)
protected void AddChildCall (ControlBuilder parent, ControlBuilder child)
{
+ if (parent == null || child == null)
+ return;
CodeMethodReferenceExpression m = new CodeMethodReferenceExpression (thisRef, child.method.Name);
CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression (m);
- object [] atts = child.ControlType.GetCustomAttributes (typeof (PartialCachingAttribute), true);
+ object [] atts = null;
+
+ if (child.ControlType != null)
+ child.ControlType.GetCustomAttributes (typeof (PartialCachingAttribute), true);
if (atts != null && atts.Length > 0) {
PartialCachingAttribute pca = (PartialCachingAttribute) atts [0];
CodeTypeReferenceExpression cc = new CodeTypeReferenceExpression("System.Web.UI.StaticPartialCachingControl");
{
CodePropertyReferenceExpression prop = new CodePropertyReferenceExpression (ctrlVar, name);
- CodeObjectCreateExpression newBuild = new CodeObjectCreateExpression (typeof (BuildTemplateMethod));
- newBuild.Parameters.Add (new CodeMethodReferenceExpression (thisRef, methodName));
+ CodeDelegateCreateExpression newBuild = new CodeDelegateCreateExpression (
+ new CodeTypeReference (typeof (BuildTemplateMethod)), thisRef, methodName);
CodeObjectCreateExpression newCompiled = new CodeObjectCreateExpression (typeof (CompiledTemplateBuilder));
newCompiled.Parameters.Add (newBuild);
{
CodePropertyReferenceExpression prop = new CodePropertyReferenceExpression (ctrlVar, name);
- CodeObjectCreateExpression newBuild = new CodeObjectCreateExpression (typeof (BuildTemplateMethod));
- newBuild.Parameters.Add (new CodeMethodReferenceExpression (thisRef, methodName));
+ CodeDelegateCreateExpression newBuild = new CodeDelegateCreateExpression (
+ new CodeTypeReference (typeof (BuildTemplateMethod)), thisRef, methodName);
- CodeObjectCreateExpression newExtract = new CodeObjectCreateExpression (typeof (ExtractTemplateValuesMethod));
- newExtract.Parameters.Add (new CodeMethodReferenceExpression (thisRef, extractMethodName));
+ CodeDelegateCreateExpression newExtract = new CodeDelegateCreateExpression (
+ new CodeTypeReference (typeof (ExtractTemplateValuesMethod)), thisRef, extractMethodName);
CodeObjectCreateExpression newCompiled = new CodeObjectCreateExpression (typeof (CompiledBindableTemplateBuilder));
newCompiled.Parameters.Add (newBuild);
void AddContentTemplateInvocation (ContentBuilderInternal cbuilder, CodeMemberMethod method, string methodName)
{
- CodeObjectCreateExpression newBuild = new CodeObjectCreateExpression (typeof (BuildTemplateMethod));
- newBuild.Parameters.Add (new CodeMethodReferenceExpression (thisRef, methodName));
+ CodeDelegateCreateExpression newBuild = new CodeDelegateCreateExpression (
+ new CodeTypeReference (typeof (BuildTemplateMethod)), thisRef, methodName);
CodeObjectCreateExpression newCompiled = new CodeObjectCreateExpression (typeof (CompiledTemplateBuilder));
newCompiled.Parameters.Add (newBuild);
TemplateBuilder tb = builder as TemplateBuilder;
if (tb != null && tb.ContainerType != null)
return tb.ContainerType;
-
+#if NET_2_0
+ return builder.BindingContainerType;
+#else
Type type = builder.BindingContainerType;
PropertyInfo prop = type.GetProperty ("Items", noCaseFlags & ~BindingFlags.NonPublic);
return type;
return prop.PropertyType;
+#endif
}
CodeMemberMethod CreateDBMethod (string name, Type container, Type target)
{
EnsureID (builder);
bool isTemplate = (typeof (TemplateBuilder).IsAssignableFrom (builder.GetType ()));
+
if (!isTemplate && !inTemplate) {
CreateField (builder, true);
} else if (!isTemplate) {
- builder.ID = builder.GetNextID (null);
- CreateField (builder, false);
+ bool doCheck = false;
+
+#if NET_2_0
+ 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
+ else
+ doCheck = true;
+#endif
+ CreateField (builder, doCheck);
}
InitMethod (builder, isTemplate, childrenAsProperties);
StringBuilder sb = new StringBuilder ();
foreach (object b in builder.Children) {
-
if (b is string) {
sb.Append ((string) b);
continue;
if (!childrenAsProperties && typeof (Control).IsAssignableFrom (builder.ControlType))
builder.method.Statements.Add (new CodeMethodReturnStatement (ctrlVar));
- }
+#if NET_2_0
+ if (builder is RootBuilder)
+ if (!String.IsNullOrEmpty (parser.MetaResourceKey))
+ AssignPropertiesFromResources (builder.method, parser.BaseType, parser.MetaResourceKey);
+#endif
+ }
+
protected internal override void CreateMethods ()
{
base.CreateMethods ();
}
CreateApplicationInstance ();
- CreateTemplateSourceDirectory ();
- }
-
- void CreateTemplateSourceDirectory ()
- {
- CodeMemberProperty prop = new CodeMemberProperty ();
- prop.Type = new CodeTypeReference (typeof (string));
- prop.Name = "TemplateSourceDirectory";
- prop.Attributes = MemberAttributes.Public | MemberAttributes.Override;
-
- CodePrimitiveExpression expr = new CodePrimitiveExpression (parser.BaseVirtualDir);
- prop.GetStatements.Add (new CodeMethodReturnStatement (expr));
- mainClass.Members.Add (prop);
}
-
+
void CreateApplicationInstance ()
{
CodeMemberProperty prop = new CodeMemberProperty ();
CodeCastExpression cast = new CodeCastExpression (appType.FullName, propRef);
prop.GetStatements.Add (new CodeMethodReturnStatement (cast));
+#if NET_2_0
+ if (partialClass != null)
+ partialClass.Members.Add (prop);
+ else
+#endif
mainClass.Members.Add (prop);
}
fldRef = new CodeFieldReferenceExpression (mainClassExpr, "__autoHandlers");
ret.Expression = fldRef;
prop.GetStatements.Add (ret);
-
prop.SetStatements.Add (new CodeAssignStatement (fldRef, new CodePropertySetValueReferenceExpression ()));
+#if NET_2_0
+ CodeAttributeDeclaration attr = new CodeAttributeDeclaration ("System.Obsolete");
+ prop.CustomAttributes.Add (attr);
+#endif
+
mainClass.Members.Add (prop);
// Add the __autoHandlers field
return str;
}
#endif
-
- CodeExpression GetExpressionFromString (Type type, string str, MemberInfo member)
- {
+
+ TypeConverter GetConverterForMember (MemberInfo member)
+ {
+ TypeConverterAttribute tca = null;
+ object[] attrs;
+
#if NET_2_0
- Type origType = type;
- 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.ConvertFrom (str);
+ TypeConverter converter = preConverted ? cvt :
+ wasNullable ? TypeDescriptor.GetConverter (type) :
+ TypeDescriptor.GetProperties (member.DeclaringType) [member.Name].Converter;
- if (converter.CanConvertTo (typeof (InstanceDescriptor))) {
+ 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));
- 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);
+ Console.WriteLine ("Unknown type: " + type + " value: " + 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];
{
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 ()});
+ ConstructorInfo c = typeof(System.Web.UI.WebControls.Unit).GetConstructor (
+ BindingFlags.Instance | BindingFlags.Public,
+ null,
+ new Type[] {typeof(double), typeof(System.Web.UI.WebControls.UnitType)},
+ null);
+
+ return new InstanceDescriptor (c, new object[] {s.Value, s.Type});
}
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 ()});
+
+ Type cParamType = null;
+ object cParam = null;
+
+ switch (s.Type) {
+ case FontSize.AsUnit:
+ case FontSize.NotSet:
+ cParamType = typeof (System.Web.UI.WebControls.Unit);
+ cParam = s.Unit;
+ break;
+
+ default:
+ cParamType = typeof (string);
+ cParam = s.Type.ToString ();
+ break;
+ }
+
+ ConstructorInfo c = typeof(System.Web.UI.WebControls.FontUnit).GetConstructor (
+ BindingFlags.Instance | BindingFlags.Public,
+ null,
+ new Type[] {cParamType},
+ null);
+ if (c != null)
+ return new InstanceDescriptor (c, new object[] {cParam});
}
return null;
}