//
// Authors:
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+// Marek Habersack (mhabersack@novell.com)
//
// (C) 2003 Ximian, Inc (http://www.ximian.com)
-//
+// (C) 2004-2008 Novell, Inc (http://novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
using System.CodeDom;
using System.Collections;
using System.ComponentModel;
+using System.Configuration;
+using System.Collections.Specialized;
+using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.Reflection;
+using System.Resources;
using System.Text;
using System.Web;
+using System.Web.Configuration;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Util;
using System.ComponentModel.Design.Serialization;
-#if NET_2_0
-using System.Configuration;
-using System.Collections.Specialized;
-using System.Collections.Generic;
using System.Text.RegularExpressions;
-using System.Web.Configuration;
-#endif
namespace System.Web.Compilation
{
{
static BindingFlags noCaseFlags = BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.IgnoreCase;
-
+ static Type monoTypeType = Type.GetType ("System.MonoType");
+
TemplateControlParser parser;
int dataBoundAtts;
internal ILocation currentLocation;
internal static CodeVariableReferenceExpression ctrlVar = new CodeVariableReferenceExpression ("__ctrl");
-#if NET_2_0
- static Regex bindRegex = new Regex (@"Bind\s*\(""(.*?)""\)\s*%>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
- static Regex bindRegexInValue = new Regex (@"Bind\s*\(""(.*?)""\)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
-#endif
+ List <string> masterPageContentPlaceHolders;
+ static Regex startsWithBindRegex = new Regex (@"^Bind\s*\(", RegexOptions.Compiled | RegexOptions.IgnoreCase);
+ // When modifying those, make sure to look at the SanitizeBindCall to make sure it
+ // picks up correct groups.
+ static Regex bindRegex = new Regex (@"Bind\s*\(\s*[""']+(.*?)[""']+((\s*,\s*[""']+(.*?)[""']+)?)\s*\)\s*%>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
+ static Regex bindRegexInValue = new Regex (@"Bind\s*\(\s*[""']+(.*?)[""']+((\s*,\s*[""']+(.*?)[""']+)?)\s*\)\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
+ static Regex evalRegexInValue = new Regex (@"(.*)Eval\s*\(\s*[""']+(.*?)[""']+((\s*,\s*[""']+(.*?)[""']+)?)\s*\)(.*)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
+
+ List <string> MasterPageContentPlaceHolders {
+ get {
+ if (masterPageContentPlaceHolders == null)
+ masterPageContentPlaceHolders = new List <string> ();
+ return masterPageContentPlaceHolders;
+ }
+ }
public TemplateControlCompiler (TemplateControlParser parser)
: base (parser)
{
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;
+ currentLocation = builder.Location;
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 = ma;
-#if NET_2_0
field.Type.Options |= CodeTypeReferenceOptions.GlobalReference;
if (partialClass != null)
partialClass.Members.Add (AddLinePragma (field, builder));
else
-#endif
mainClass.Members.Add (AddLinePragma (field, builder));
}
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;
void AddParsedSubObjectStmt (ControlBuilder builder, CodeExpression expr)
{
- if (!builder.haveParserVariable) {
+ if (!builder.HaveParserVariable) {
CodeVariableDeclarationStatement p = new CodeVariableDeclarationStatement();
p.Name = "__parser";
p.Type = new CodeTypeReference (typeof (IParserAccessor));
p.InitExpression = new CodeCastExpression (typeof (IParserAccessor), ctrlVar);
- builder.methodStatements.Add (p);
- builder.haveParserVariable = true;
+ builder.MethodStatements.Add (p);
+ builder.HaveParserVariable = true;
}
CodeVariableReferenceExpression var = new CodeVariableReferenceExpression ("__parser");
CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (var, "AddParsedSubObject");
invoke.Parameters.Add (expr);
- builder.methodStatements.Add (AddLinePragma (invoke, builder));
+ builder.MethodStatements.Add (AddLinePragma (invoke, builder));
}
void InitMethod (ControlBuilder builder, bool isTemplate, bool childrenAsProperties)
{
- currentLocation = builder.location;
+ currentLocation = builder.Location;
string tailname = ((builder is RootBuilder) ? "Tree" : ("_" + builder.ID));
CodeMemberMethod method = new CodeMemberMethod ();
- builder.method = method;
- builder.methodStatements = method.Statements;
+ builder.Method = method;
+ builder.MethodStatements = method.Statements;
method.Name = "__BuildControl" + tailname;
method.Attributes = MemberAttributes.Private | MemberAttributes.Final;
* method, allow subclasses to insert control
* specific code. */
if (builder is RootBuilder) {
-#if NET_2_0
SetCustomAttributes (method);
-#endif
AddStatementsToInitMethod (method);
}
if (builder.HasAspCode) {
CodeMemberMethod renderMethod = new CodeMemberMethod ();
- builder.renderMethod = renderMethod;
+ builder.RenderMethod = renderMethod;
renderMethod.Name = "__Render" + tailname;
renderMethod.Attributes = MemberAttributes.Private | MemberAttributes.Final;
CodeParameterDeclarationExpression arg1 = new CodeParameterDeclarationExpression ();
if (builder is RootBuilder)
typeString = parser.ClassName;
else {
- if (builder.ControlType != null && builder.isProperty &&
+ if (builder.ControlType != null && builder.IsProperty &&
!typeof (ITemplate).IsAssignableFrom (builder.ControlType))
typeString = builder.ControlType.FullName;
else
typeString = "System.Web.UI.Control";
+ ProcessTemplateChildren (builder);
}
method.Parameters.Add (new CodeParameterDeclarationExpression (typeString, "__ctrl"));
method.Statements.Add (initAsControl);
}
-#if NET_2_0
if (builder.ParentTemplateBuilder is System.Web.UI.WebControls.ContentBuilderInternal) {
PropertyInfo pi;
// CreateAssignStatementsFromAttributes
// below.
//
- if (builder.attribs != null) {
- string skinid = builder.attribs ["skinid"] as string;
- if (skinid != null)
- CreateAssignStatementFromAttribute (builder, "skinid");
- }
+ string skinid = builder.GetAttribute ("skinid");
+ if (!String.IsNullOrEmpty (skinid))
+ CreateAssignStatementFromAttribute (builder, "skinid");
+
if (typeof (WebControl).IsAssignableFrom (type)) {
CodeMethodInvokeExpression applyStyleSheetSkin = new CodeMethodInvokeExpression (ctrlVar, "ApplyStyleSheetSkin");
if (typeof (Page).IsAssignableFrom (parser.BaseType))
applyStyleSheetSkin.Parameters.Add (new CodePropertyReferenceExpression (thisRef, "Page"));
method.Statements.Add (applyStyleSheetSkin);
}
-#endif
+
+ // Process template children before anything else
+ ProcessTemplateChildren (builder);
// 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
+ string ctl_id = builder.GetAttribute ("id");
+ if (ctl_id != null && ctl_id.Length != 0)
+ CreateAssignStatementFromAttribute (builder, "id");
+
if (typeof (ContentPlaceHolder).IsAssignableFrom (type)) {
- CodePropertyReferenceExpression prop = new CodePropertyReferenceExpression (thisRef, "ContentPlaceHolders");
- CodeMethodInvokeExpression addPlaceholder = new CodeMethodInvokeExpression (prop, "Add");
- addPlaceholder.Parameters.Add (ctrlVar);
- method.Statements.Add (addPlaceholder);
-
+ List <string> placeHolderIds = MasterPageContentPlaceHolders;
+ string cphID = builder.ID;
+
+ if (!placeHolderIds.Contains (cphID))
+ placeHolderIds.Add (cphID);
CodeConditionStatement condStatement;
// Add the __Template_* field
- CodeMemberField fld = new CodeMemberField (typeof (ITemplate), "__Template_" + builder.ID);
+ string templateField = "__Template_" + cphID;
+ CodeMemberField fld = new CodeMemberField (typeof (ITemplate), templateField);
fld.Attributes = MemberAttributes.Private;
mainClass.Members.Add (fld);
CodeFieldReferenceExpression templateID = new CodeFieldReferenceExpression ();
templateID.TargetObject = thisRef;
- templateID.FieldName = "__Template_" + builder.ID;
+ templateID.FieldName = templateField;
+ CreateContentPlaceHolderTemplateProperty (templateField, "Template_" + cphID);
+
// if ((this.ContentTemplates != null)) {
// this.__Template_$builder.ID = ((System.Web.UI.ITemplate)(this.ContentTemplates["$builder.ID"]));
// }
CodeIndexerExpression indexer = new CodeIndexerExpression ();
indexer.TargetObject = new CodePropertyReferenceExpression (thisRef, "ContentTemplates");
- indexer.Indices.Add (new CodePrimitiveExpression (builder.ID));
+ indexer.Indices.Add (new CodePrimitiveExpression (cphID));
assign = new CodeAssignStatement ();
assign.Left = templateID;
method.Statements.Add (condStatement);
// this is the bit that causes the following stuff to end up in the else { }
- builder.methodStatements = condStatement.FalseStatements;
+ builder.MethodStatements = condStatement.FalseStatements;
}
-#endif
}
mainClass.Members.Add (method);
}
-#if NET_2_0
+ void ProcessTemplateChildren (ControlBuilder builder)
+ {
+ ArrayList templates = builder.TemplateChildren;
+ if (templates != null && templates.Count > 0) {
+ foreach (TemplateBuilder tb in templates) {
+ CreateControlTree (tb, true, false);
+ if (tb.BindingDirection == BindingDirection.TwoWay) {
+ string extractMethod = CreateExtractValuesMethod (tb);
+ AddBindableTemplateInvocation (builder, tb.TagName, tb.Method.Name, extractMethod);
+ } else
+ AddTemplateInvocation (builder, tb.TagName, tb.Method.Name);
+ }
+ }
+ }
+
void SetCustomAttribute (CodeMemberMethod method, UnknownAttributeDescriptor uad)
{
CodeAssignStatement assign = new CodeAssignStatement ();
foreach (UnknownAttributeDescriptor uad in attrs)
SetCustomAttribute (method, uad);
}
-#endif
protected virtual void AddStatementsToInitMethod (CodeMemberMethod method)
{
CodeMethodInvokeExpression expr;
expr = new CodeMethodInvokeExpression (methodRef, new CodePrimitiveExpression (str));
- builder.renderMethod.Statements.Add (AddLinePragma (expr, builder));
+ builder.RenderMethod.Statements.Add (expr);
}
}
- string TrimDB (string value)
+ string TrimDB (string value, bool trimTail)
{
string str = value.Trim ();
- str = str.Substring (3);
- return str.Substring (0, str.Length - 2);
+ int len = str.Length;
+ int idx = str.IndexOf ('#', 2) + 1;
+ if (idx >= len)
+ return String.Empty;
+ if (trimTail)
+ len -= 2;
+
+ return str.Substring (idx, len - idx).Trim ();
+ }
+
+ CodeExpression CreateEvalInvokeExpression (Regex regex, string value, bool isBind)
+ {
+ Match match = regex.Match (value);
+ if (!match.Success) {
+ if (isBind)
+ throw new HttpParseException ("Bind invocation wasn't formatted properly.");
+ return null;
+ }
+
+ string sanitizedSnippet;
+ if (isBind)
+ sanitizedSnippet = SanitizeBindCall (match);
+ else
+ sanitizedSnippet = value;
+
+ return new CodeSnippetExpression (sanitizedSnippet);
}
+ string SanitizeBindCall (Match match)
+ {
+ GroupCollection groups = match.Groups;
+ StringBuilder sb = new StringBuilder ("Eval(\"" + groups [1] + "\"");
+ Group second = groups [4];
+ if (second != null) {
+ string v = second.Value;
+ if (v != null && v.Length > 0)
+ sb.Append (",\"" + second + "\"");
+ }
+
+ sb.Append (")");
+ return sb.ToString ();
+ }
+
string DataBoundProperty (ControlBuilder builder, Type type, string varName, string value)
{
- value = TrimDB (value);
+ value = TrimDB (value, true);
CodeMemberMethod method;
- string dbMethodName = builder.method.Name + "_DB_" + dataBoundAtts++;
-#if NET_2_0
- bool need_if = false;
+ string dbMethodName = builder.Method.Name + "_DB_" + dataBoundAtts++;
+ CodeExpression valueExpression = null;
value = value.Trim ();
- if (StrUtils.StartsWith (value, "Bind", true)) {
- Match match = bindRegexInValue.Match (value);
- if (match.Success) {
- value = "Eval" + value.Substring (4);
+
+ bool need_if = false;
+ if (startsWithBindRegex.Match (value).Success) {
+ valueExpression = CreateEvalInvokeExpression (bindRegexInValue, value, true);
+ if (valueExpression != null)
need_if = true;
- }
- }
-#endif
- method = CreateDBMethod (builder, dbMethodName, GetContainerType (builder), builder.ControlType);
+ } else
+ if (StrUtils.StartsWith (value, "Eval", true))
+ valueExpression = CreateEvalInvokeExpression (evalRegexInValue, value, false);
+
+ if (valueExpression == null)
+ valueExpression = new CodeSnippetExpression (value);
+ method = CreateDBMethod (builder, dbMethodName, GetContainerType (builder), builder.ControlType);
CodeVariableReferenceExpression targetExpr = new CodeVariableReferenceExpression ("target");
// This should be a CodePropertyReferenceExpression for properties... but it works anyway
CodeMethodInvokeExpression tostring = new CodeMethodInvokeExpression ();
CodeTypeReferenceExpression conv = new CodeTypeReferenceExpression (typeof (Convert));
tostring.Method = new CodeMethodReferenceExpression (conv, "ToString");
- tostring.Parameters.Add (new CodeSnippetExpression (value));
+ tostring.Parameters.Add (valueExpression);
expr = tostring;
- } else {
- CodeSnippetExpression snippet = new CodeSnippetExpression (value);
- expr = new CodeCastExpression (type, snippet);
- }
+ } else
+ expr = new CodeCastExpression (type, valueExpression);
CodeAssignStatement assign = new CodeAssignStatement (field, expr);
-#if NET_2_0
if (need_if) {
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);
method.Statements.Add (ccs);
- }
- else
-#endif
+ } else
method.Statements.Add (assign);
mainClass.Members.Add (method);
}
void AddCodeForPropertyOrField (ControlBuilder builder, Type type, string var_name, string att, MemberInfo member, bool isDataBound, bool isExpression)
- {
- CodeMemberMethod method = builder.method;
+ {
+ CodeMemberMethod method = builder.Method;
bool isWritable = IsWritablePropertyOrField (member);
+
if (isDataBound && isWritable) {
string dbMethodName = DataBoundProperty (builder, type, var_name, att);
AddEventAssign (method, builder, "DataBinding", typeof (EventHandler), dbMethodName);
return;
- }
-#if NET_2_0
- else if (isExpression && isWritable) {
+ } else if (isExpression && isWritable) {
AddExpressionAssign (method, builder, member, type, var_name, att);
return;
}
-#endif
-
+
CodeAssignStatement assign = new CodeAssignStatement ();
assign.Left = new CodePropertyReferenceExpression (ctrlVar, var_name);
- currentLocation = builder.location;
+ currentLocation = builder.Location;
assign.Right = GetExpressionFromString (type, att, member);
method.Statements.Add (AddLinePragma (assign, builder));
}
- bool IsDataBound (string value)
+ bool IsDirective (string value, char directiveChar)
{
- if (value == null || value == "")
+ if (value == null || value == String.Empty)
+ return false;
+
+ value = value.Trim ();
+ if (!StrUtils.StartsWith (value, "<%") || !StrUtils.EndsWith (value, "%>"))
return false;
- string str = value.Trim ();
- return (StrUtils.StartsWith (str, "<%#") && StrUtils.EndsWith (str, "%>"));
+ int dcIndex = value.IndexOf (directiveChar, 2);
+ if (dcIndex == -1)
+ return false;
+
+ if (dcIndex == 2)
+ return true;
+ dcIndex--;
+
+ while (dcIndex >= 2) {
+ if (!Char.IsWhiteSpace (value [dcIndex]))
+ return false;
+ dcIndex--;
+ }
+
+ return true;
+ }
+
+ bool IsDataBound (string value)
+ {
+ return IsDirective (value, '#');
}
-#if NET_2_0
bool IsExpression (string value)
{
- if (value == null || value == "")
- return false;
- string str = value.Trim ();
- return (StrUtils.StartsWith (str, "<%$") && StrUtils.EndsWith (str, "%>"));
+ return IsDirective (value, '$');
}
void RegisterBindingInfo (ControlBuilder builder, string propName, ref string value)
{
- string str = value.Trim ();
- str = str.Substring (3).Trim (); // eats "<%#"
+ string str = TrimDB (value, false);
if (StrUtils.StartsWith (str, "Bind", true)) {
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)
+
+ if (templateBuilder == null)
throw new HttpException ("Bind expression not allowed in this context.");
-
- string id = builder.attribs ["ID"] as string;
- if (id == null)
+
+ if (templateBuilder.BindingDirection == BindingDirection.OneWay)
+ return;
+
+ string id = builder.GetAttribute ("ID");
+ if (String.IsNullOrEmpty (id))
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);
}
}
}
-#endif
/*
static bool InvariantCompare (string a, string b)
{
- return (0 == String.Compare (a, b, false, CultureInfo.InvariantCulture));
+ return (0 == String.Compare (a, b, false, Helpers.InvariantCulture));
}
*/
static bool InvariantCompareNoCase (string a, string b)
{
- return (0 == String.Compare (a, b, true, CultureInfo.InvariantCulture));
+ return (0 == String.Compare (a, b, true, Helpers.InvariantCulture));
}
static MemberInfo GetFieldOrProperty (Type type, string name)
{
PropertyInfo pi = member as PropertyInfo;
if (pi != null)
- return pi.CanWrite;
+ return pi.GetSetMethod (false) != null;
FieldInfo fi = member as FieldInfo;
if (fi != null)
return !fi.IsInitOnly;
int hyphen = id.IndexOf ('-');
bool isPropertyInfo = (member is PropertyInfo);
bool isDataBound = IsDataBound (attValue);
-#if NET_2_0
bool isExpression = !isDataBound && IsExpression (attValue);
-#else
- bool isExpression = false;
-#endif
Type type;
if (isPropertyInfo) {
type = ((PropertyInfo) member).PropertyType;
}
if (InvariantCompareNoCase (member.Name, id)) {
-#if NET_2_0
if (isDataBound)
- RegisterBindingInfo (builder, member.Name, ref attValue);
-
-#endif
+ RegisterBindingInfo (builder, member.Name, ref attValue);
+
if (!IsWritablePropertyOrField (member))
return false;
-
+
AddCodeForPropertyOrField (builder, type, member.Name, attValue, member, isDataBound, isExpression);
return true;
}
if (hyphen == -1)
return false;
- string prop_field = id.Replace ("-", ".");
+ string prop_field = id.Replace ('-', '.');
string [] parts = prop_field.Split (new char [] {'.'});
int length = parts.Length;
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
+
+ if (isDataBound)
+ RegisterBindingInfo (builder, prefix + member.Name + "." + subprop.Name, ref attValue);
+
AddCodeForPropertyOrField (builder, subprop.PropertyType,
prefix + member.Name + "." + subprop.Name,
val, subprop, isDataBound, isExpression);
return true;
}
-#if NET_2_0
- void AddExpressionAssign (CodeMemberMethod method, ControlBuilder builder, MemberInfo member, Type type, string name, string value)
+ CodeExpression CompileExpression (MemberInfo member, Type type, string value, bool useSetAttribute)
{
- CodeAssignStatement assign = new CodeAssignStatement ();
- assign.Left = new CodePropertyReferenceExpression (ctrlVar, name);
-
// First let's find the correct expression builder
value = value.Substring (3, value.Length - 5).Trim ();
int colon = value.IndexOf (':');
if (colon == -1)
- return;
+ return null;
string prefix = value.Substring (0, colon).Trim ();
string expr = value.Substring (colon + 1).Trim ();
- System.Configuration.Configuration config = WebConfigurationManager.OpenWebConfiguration ("");
- if (config == null)
- return;
- CompilationSection cs = (CompilationSection)config.GetSection ("system.web/compilation");
+ CompilationSection cs = (CompilationSection)WebConfigurationManager.GetWebApplicationSection ("system.web/compilation");
if (cs == null)
- return;
+ return null;
+
if (cs.ExpressionBuilders == null || cs.ExpressionBuilders.Count == 0)
- return;
+ return null;
System.Web.Configuration.ExpressionBuilder ceb = cs.ExpressionBuilders[prefix];
if (ceb == null)
- return;
+ return null;
+
string builderType = ceb.Type;
-
Type t;
+
try {
t = HttpApplication.LoadType (builderType, true);
} catch (Exception e) {
- throw new HttpException (
- String.Format ("Failed to load expression builder type `{0}'", builderType), e);
+ throw new HttpException (String.Format ("Failed to load expression builder type `{0}'", builderType), e);
}
if (!typeof (System.Web.Compilation.ExpressionBuilder).IsAssignableFrom (t))
- throw new HttpException (
- String.Format (
- "Type {0} is not descendant from System.Web.Compilation.ExpressionBuilder",
- builderType));
+ throw new HttpException (String.Format ("Type {0} is not descendant from System.Web.Compilation.ExpressionBuilder", builderType));
System.Web.Compilation.ExpressionBuilder eb = null;
object parsedData;
ctx = new ExpressionBuilderContext (HttpContext.Current.Request.FilePath);
parsedData = eb.ParseExpression (expr, type, ctx);
} catch (Exception e) {
- throw new HttpException (
- String.Format ("Failed to create an instance of type `{0}'", builderType), e);
+ throw new HttpException (String.Format ("Failed to create an instance of type `{0}'", builderType), e);
}
- BoundPropertyEntry bpe = CreateBoundPropertyEntry (member as PropertyInfo, prefix, expr);
- assign.Right = eb.GetCodeExpression (bpe, parsedData, ctx);
+ BoundPropertyEntry bpe = CreateBoundPropertyEntry (member as PropertyInfo, prefix, expr, useSetAttribute);
+ return eb.GetCodeExpression (bpe, parsedData, ctx);
+ }
+
+ void AddExpressionAssign (CodeMemberMethod method, ControlBuilder builder, MemberInfo member, Type type, string name, string value)
+ {
+ CodeExpression expr = CompileExpression (member, type, value, false);
+
+ if (expr == null)
+ return;
- builder.method.Statements.Add (AddLinePragma (assign, builder));
+ CodeAssignStatement assign = new CodeAssignStatement ();
+ assign.Left = new CodePropertyReferenceExpression (ctrlVar, name);
+ assign.Right = expr;
+
+ builder.Method.Statements.Add (AddLinePragma (assign, builder));
}
- BoundPropertyEntry CreateBoundPropertyEntry (PropertyInfo pi, string prefix, string expr)
+ BoundPropertyEntry CreateBoundPropertyEntry (PropertyInfo pi, string prefix, string expr, bool useSetAttribute)
{
- 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;
-
+ if (pi != null) {
+ ret.Name = pi.Name;
+ ret.PropertyInfo = pi;
+ ret.Type = pi.PropertyType;
+ }
+ ret.UseSetAttribute = useSetAttribute;
+
return ret;
}
+
+ bool ResourceProviderHasObject (string key)
+ {
+ IResourceProvider rp = HttpContext.GetResourceProvider (InputVirtualPath.Absolute, true);
+ if (rp == null)
+ return false;
+
+ IResourceReader rr = rp.ResourceReader;
+ if (rr == null)
+ return false;
+
+ try {
+ IDictionaryEnumerator ide = rr.GetEnumerator ();
+ if (ide == null)
+ return false;
+
+ string dictKey;
+ while (ide.MoveNext ()) {
+ dictKey = ide.Key as string;
+ if (String.IsNullOrEmpty (dictKey))
+ continue;
+ if (String.Compare (key, dictKey, StringComparison.Ordinal) == 0)
+ return true;
+ }
+ } finally {
+ rr.Close ();
+ }
+
+ return false;
+ }
void AssignPropertyFromResources (ControlBuilder builder, MemberInfo mi, string attvalue)
{
if (!isProperty && !isField || !IsWritablePropertyOrField (mi))
return;
+ object[] attrs = mi.GetCustomAttributes (typeof (LocalizableAttribute), true);
+ if (attrs != null && attrs.Length > 0 && !((LocalizableAttribute)attrs [0]).IsLocalizable)
+ return;
+
string memberName = mi.Name;
string resname = String.Concat (attvalue, ".", memberName);
+ if (!ResourceProviderHasObject (resname))
+ return;
+
// __ctrl.Text = System.Convert.ToString(HttpContext.GetLocalResourceObject("ButtonResource1.Text"));
string inputFile = parser.InputFile;
string physPath = HttpContext.Current.Request.PhysicalApplicationPath;
if (!isProperty && !isField)
return; // an "impossible" case
- Type declaringType = mi.DeclaringType;
CodeAssignStatement assign = new CodeAssignStatement ();
assign.Left = new CodePropertyReferenceExpression (ctrlVar, memberName);
assign.Right = ResourceExpressionBuilder.CreateGetLocalResourceObject (mi, resname);
- builder.method.Statements.Add (AddLinePragma (assign, builder));
+ builder.Method.Statements.Add (AddLinePragma (assign, builder));
}
void AssignPropertiesFromResources (ControlBuilder builder, Type controlType, string attvalue)
AssignPropertiesFromResources (builder, controlType, attvalue);
}
-#endif
void AddEventAssign (CodeMemberMethod method, ControlBuilder builder, string name, Type type, string value)
{
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"){
+ string attvalue = builder.GetAttribute (id);
+ if (id.Length > 2 && String.Compare (id.Substring (0, 2), "ON", true, Helpers.InvariantCulture) == 0){
if (ev_info == null)
ev_info = type.GetEvents ();
string id_as_event = id.Substring (2);
foreach (EventInfo ev in ev_info){
if (InvariantCompareNoCase (ev.Name, id_as_event)){
- AddEventAssign (builder.method,
+ AddEventAssign (builder.Method,
builder,
ev.Name,
ev.EventHandlerType,
}
-#if NET_2_0
- if (id.ToLower () == "meta:resourcekey") {
+ if (String.Compare (id, "meta:resourcekey", StringComparison.OrdinalIgnoreCase) == 0) {
AssignPropertiesFromResources (builder, attvalue);
return;
}
-#endif
int hyphen = id.IndexOf ('-');
string alt_id = id;
}
if (!typeof (IAttributeAccessor).IsAssignableFrom (type))
- throw new ParseException (builder.location, "Unrecognized attribute: " + id);
+ throw new ParseException (builder.Location, "Unrecognized attribute: " + id);
- string val;
- CodeMemberMethod method = builder.method;
- bool databound = IsDataBound (attvalue);
+ CodeMemberMethod method = builder.Method;
+ bool isDatabound = IsDataBound (attvalue);
+ bool isExpression = !isDatabound && IsExpression (attvalue);
- if (databound) {
- val = attvalue.Substring (3);
- val = val.Substring (0, val.Length - 2);
- CreateDBAttributeMethod (builder, id, val);
+ if (isDatabound) {
+ string value = attvalue.Substring (3, attvalue.Length - 5).Trim ();
+ CodeExpression valueExpression = null;
+ if (startsWithBindRegex.Match (value).Success)
+ valueExpression = CreateEvalInvokeExpression (bindRegexInValue, value, true);
+ else
+ if (StrUtils.StartsWith (value, "Eval", true))
+ valueExpression = CreateEvalInvokeExpression (evalRegexInValue, value, false);
+
+ if (valueExpression == null && value != null && value.Trim () != String.Empty)
+ valueExpression = new CodeSnippetExpression (value);
+
+ CreateDBAttributeMethod (builder, id, valueExpression);
} else {
CodeCastExpression cast;
CodeMethodReferenceExpression methodExpr;
methodExpr = new CodeMethodReferenceExpression (cast, "SetAttribute");
expr = new CodeMethodInvokeExpression (methodExpr);
expr.Parameters.Add (new CodePrimitiveExpression (id));
- expr.Parameters.Add (new CodePrimitiveExpression (attvalue));
+
+ CodeExpression valueExpr = null;
+ if (isExpression)
+ valueExpr = CompileExpression (null, typeof (string), attvalue, true);
+
+ if (valueExpr == null)
+ valueExpr = new CodePrimitiveExpression (attvalue);
+
+ expr.Parameters.Add (valueExpr);
method.Statements.Add (AddLinePragma (expr, builder));
}
-
}
protected void CreateAssignStatementsFromAttributes (ControlBuilder builder)
{
-#if NET_2_0
- bool haveMetaKey = false;
-#endif
this.dataBoundAtts = 0;
- IDictionary atts = builder.attribs;
+ IDictionary atts = builder.Attributes;
if (atts == null || atts.Count == 0)
return;
continue;
// ID is assigned in BuildControltree
if (InvariantCompareNoCase (id, "id"))
- continue;
-
-#if NET_2_0
+ continue;
+
/* we skip SkinID here as it's assigned in BuildControlTree */
if (InvariantCompareNoCase (id, "skinid"))
continue;
- if (InvariantCompareNoCase (id, "meta:resourcekey")) {
- haveMetaKey = true;
- continue;
- }
-#endif
+ if (InvariantCompareNoCase (id, "meta:resourcekey"))
+ continue; // ignore, this one's processed at the very end of
+ // the method
CreateAssignStatementFromAttribute (builder, id);
}
-
-#if NET_2_0
- if (haveMetaKey)
- CreateAssignStatementFromAttribute (builder, "meta:resourcekey");
-#endif
}
- void CreateDBAttributeMethod (ControlBuilder builder, string attr, string code)
+ void CreateDBAttributeMethod (ControlBuilder builder, string attr, CodeExpression code)
{
- if (code == null || code.Trim () == "")
+ if (code == null)
return;
string id = builder.GetNextID (null);
string dbMethodName = "__DataBind_" + id;
- CodeMemberMethod method = builder.method;
+ CodeMemberMethod method = builder.Method;
AddEventAssign (method, builder, "DataBinding", typeof (EventHandler), dbMethodName);
method = CreateDBMethod (builder, dbMethodName, GetContainerType (builder), builder.ControlType);
+ builder.DataBindingMethod = method;
+
CodeCastExpression cast;
CodeMethodReferenceExpression methodExpr;
CodeMethodInvokeExpression expr;
tostring.Method = new CodeMethodReferenceExpression (
new CodeTypeReferenceExpression (typeof (Convert)),
"ToString");
- tostring.Parameters.Add (new CodeSnippetExpression (code));
+ tostring.Parameters.Add (code);
expr.Parameters.Add (tostring);
method.Statements.Add (expr);
mainClass.Members.Add (method);
new CodeArgumentReferenceExpression ("parameterContainer"),
"Controls");
- indexer.Indices.Add (new CodePrimitiveExpression (builder.renderIndex));
+ indexer.Indices.Add (new CodePrimitiveExpression (builder.RenderIndex));
CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (indexer, "RenderControl");
invoke.Parameters.Add (new CodeArgumentReferenceExpression ("__output"));
- builder.renderMethod.Statements.Add (invoke);
- builder.renderIndex++;
+ builder.RenderMethod.Statements.Add (invoke);
+ builder.IncreaseRenderIndex ();
}
protected void AddChildCall (ControlBuilder parent, ControlBuilder child)
if (parent == null || child == null)
return;
- CodeMethodReferenceExpression m = new CodeMethodReferenceExpression (thisRef, child.method.Name);
+ CodeMethodReferenceExpression m = new CodeMethodReferenceExpression (thisRef, child.Method.Name);
CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression (m);
object [] atts = null;
-
+
if (child.ControlType != null)
- child.ControlType.GetCustomAttributes (typeof (PartialCachingAttribute), true);
+ atts = 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");
build.Parameters.Add (new CodePrimitiveExpression (pca.VaryByCustom));
build.Parameters.Add (new CodeDelegateCreateExpression (
new CodeTypeReference (typeof (System.Web.UI.BuildMethod)),
- thisRef, child.method.Name));
+ thisRef, child.Method.Name));
- parent.methodStatements.Add (AddLinePragma (build, parent));
+ parent.MethodStatements.Add (AddLinePragma (build, parent));
if (parent.HasAspCode)
AddRenderControl (parent);
return;
}
- if (child.isProperty || parent.ChildrenAsProperties) {
+ if (child.IsProperty || parent.ChildrenAsProperties) {
expr.Parameters.Add (new CodeFieldReferenceExpression (ctrlVar, child.TagName));
- parent.methodStatements.Add (AddLinePragma (expr, parent));
+ parent.MethodStatements.Add (AddLinePragma (expr, parent));
return;
}
- parent.methodStatements.Add (AddLinePragma (expr, parent));
+ parent.MethodStatements.Add (AddLinePragma (expr, parent));
CodeFieldReferenceExpression field = new CodeFieldReferenceExpression (thisRef, child.ID);
if (parent.ControlType == null || typeof (IParserAccessor).IsAssignableFrom (parent.ControlType))
AddParsedSubObjectStmt (parent, field);
else {
CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (ctrlVar, "Add");
invoke.Parameters.Add (field);
- parent.methodStatements.Add (AddLinePragma (invoke, parent));
+ parent.MethodStatements.Add (AddLinePragma (invoke, parent));
}
if (parent.HasAspCode)
AddRenderControl (parent);
}
- void AddTemplateInvocation (CodeMemberMethod method, string name, string methodName)
+ void AddTemplateInvocation (ControlBuilder builder, string name, string methodName)
{
CodePropertyReferenceExpression prop = new CodePropertyReferenceExpression (ctrlVar, name);
newCompiled.Parameters.Add (newBuild);
CodeAssignStatement assign = new CodeAssignStatement (prop, newCompiled);
- method.Statements.Add (assign);
+ builder.Method.Statements.Add (AddLinePragma (assign, builder));
}
-#if NET_2_0
- void AddBindableTemplateInvocation (CodeMemberMethod method, string name, string methodName, string extractMethodName)
+ void AddBindableTemplateInvocation (ControlBuilder builder, string name, string methodName, string extractMethodName)
{
CodePropertyReferenceExpression prop = new CodePropertyReferenceExpression (ctrlVar, name);
newCompiled.Parameters.Add (newExtract);
CodeAssignStatement assign = new CodeAssignStatement (prop, newCompiled);
- method.Statements.Add (assign);
+ builder.Method.Statements.Add (AddLinePragma (assign, builder));
}
string CreateExtractValuesMethod (TemplateBuilder builder)
method.Statements.Add (AddLinePragma (invoke, cbuilder));
}
-#endif
void AddCodeRender (ControlBuilder parent, CodeRenderBuilder cr)
{
if (!cr.IsAssign) {
CodeSnippetStatement code = new CodeSnippetStatement (cr.Code);
- parent.renderMethod.Statements.Add (AddLinePragma (code, cr));
+ parent.RenderMethod.Statements.Add (AddLinePragma (code, cr));
return;
}
new CodeArgumentReferenceExpression ("__output"),
"Write");
- expr.Parameters.Add (new CodeSnippetExpression (cr.Code));
- parent.renderMethod.Statements.Add (AddLinePragma (expr, cr));
+ expr.Parameters.Add (GetWrappedCodeExpression (cr));
+ parent.RenderMethod.Statements.Add (AddLinePragma (expr, cr));
}
+ CodeExpression GetWrappedCodeExpression (CodeRenderBuilder cr)
+ {
+ var ret = new CodeSnippetExpression (cr.Code);
+#if NET_4_0
+ if (cr.HtmlEncode) {
+ var encodeRef = new CodeMethodReferenceExpression (new CodeTypeReferenceExpression (typeof (HttpUtility)), "HtmlEncode");
+ return new CodeMethodInvokeExpression (encodeRef, new CodeExpression[] { ret });
+ } else
+#endif
+ return ret;
+ }
+
static Type GetContainerType (ControlBuilder builder)
{
- 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);
- if (prop == null)
- return type;
-
- Type ptype = prop.PropertyType;
- if (!typeof (ICollection).IsAssignableFrom (ptype))
- return type;
-
- prop = ptype.GetProperty ("Item", noCaseFlags & ~BindingFlags.NonPublic);
- if (prop == null)
- return type;
-
- return prop.PropertyType;
-#endif
}
CodeMemberMethod CreateDBMethod (ControlBuilder builder, string name, Type container, Type target)
string dbMethodName = "__DataBind_" + db.ID;
// Add the method that builds the DataBoundLiteralControl
InitMethod (db, false, false);
- CodeMemberMethod method = db.method;
+ CodeMemberMethod method = db.Method;
AddEventAssign (method, builder, "DataBinding", typeof (EventHandler), dbMethodName);
method.Statements.Add (new CodeMethodReturnStatement (ctrlVar));
// Add the DataBind handler
method = CreateDBMethod (builder, dbMethodName, GetContainerType (builder), typeof (DataBoundLiteralControl));
+ builder.DataBindingMethod = method;
CodeVariableReferenceExpression targetExpr = new CodeVariableReferenceExpression ("target");
CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression ();
method.Statements.Add (AddLinePragma (invoke, builder));
mainClass.Members.Add (method);
-
+
AddChildCall (builder, db);
}
if (!isTemplate && !inTemplate) {
CreateField (builder, true);
} else if (!isTemplate) {
- bool doCheck = false;
-
-#if NET_2_0
+ bool doCheck = false;
bool singleInstance = false;
- ControlBuilder pb = builder.parentBuilder;
+ ControlBuilder pb = builder.ParentBuilder;
TemplateBuilder tpb;
while (pb != null) {
tpb = pb as TemplateBuilder;
if (tpb == null) {
- pb = pb.parentBuilder;
+ pb = pb.ParentBuilder;
continue;
}
}
if (!singleInstance)
-#endif
builder.ID = builder.GetNextID (null);
-#if NET_2_0
else
doCheck = true;
-#endif
+
CreateField (builder, doCheck);
}
CreateAssignStatementsFromAttributes (builder);
if (builder.Children != null && builder.Children.Count > 0) {
- ArrayList templates = null;
-
StringBuilder sb = new StringBuilder ();
foreach (object b in builder.Children) {
if (b is string) {
FlushText (builder, sb);
if (b is ObjectTagBuilder) {
ProcessObjectTag ((ObjectTagBuilder) b);
- continue;
- }
-
- StringPropertyBuilder pb = b as StringPropertyBuilder;
- if (pb != null){
+ } else if (b is StringPropertyBuilder) {
+ StringPropertyBuilder pb = b as StringPropertyBuilder;
if (pb.Children != null && pb.Children.Count > 0) {
StringBuilder asb = new StringBuilder ();
foreach (string s in pb.Children)
asb.Append (s);
- CodeMemberMethod method = builder.method;
+ CodeMemberMethod method = builder.Method;
CodeAssignStatement assign = new CodeAssignStatement ();
assign.Left = new CodePropertyReferenceExpression (ctrlVar, pb.PropertyName);
assign.Right = new CodePrimitiveExpression (asb.ToString ());
method.Statements.Add (AddLinePragma (assign, builder));
}
- continue;
- }
-
-#if NET_2_0
- if (b is ContentBuilderInternal) {
+ } else if (b is ContentBuilderInternal) {
ContentBuilderInternal cb = (ContentBuilderInternal) b;
CreateControlTree (cb, false, true);
- AddContentTemplateInvocation (cb, builder.method, cb.method.Name);
- continue;
- }
-#endif
-
- if (b is TemplateBuilder) {
- if (templates == null)
- templates = new ArrayList ();
-
- templates.Add (b);
+ AddContentTemplateInvocation (cb, builder.Method, cb.Method.Name);
continue;
}
- if (b is CodeRenderBuilder) {
+ // Ignore TemplateBuilders - they are processed in InitMethod
+ else if (b is TemplateBuilder) {
+ } else if (b is CodeRenderBuilder) {
AddCodeRender (builder, (CodeRenderBuilder) b);
- continue;
- }
-
- if (b is DataBindingBuilder) {
+ } else if (b is DataBindingBuilder) {
AddDataBindingLiteral (builder, (DataBindingBuilder) b);
- continue;
- }
-
- if (b is ControlBuilder) {
+ } else if (b is ControlBuilder) {
ControlBuilder child = (ControlBuilder) b;
CreateControlTree (child, inTemplate, builder.ChildrenAsProperties);
AddChildCall (builder, child);
continue;
- }
+ } else
+ throw new Exception ("???");
- throw new Exception ("???");
+ ControlBuilder bldr = b as ControlBuilder;
+ bldr.ProcessGeneratedCode (CompileUnit, BaseType, DerivedType, bldr.Method, bldr.DataBindingMethod);
}
FlushText (builder, sb);
-
- if (templates != null) {
- 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);
- }
- }
-
}
- if (builder.defaultPropertyBuilder != null) {
- ControlBuilder b = builder.defaultPropertyBuilder;
- CreateControlTree (b, false, true);
- AddChildCall (builder, b);
+ ControlBuilder defaultPropertyBuilder = builder.DefaultPropertyBuilder;
+ if (defaultPropertyBuilder != null) {
+ CreateControlTree (defaultPropertyBuilder, false, true);
+ AddChildCall (builder, defaultPropertyBuilder);
}
-
+
if (builder.HasAspCode) {
+ CodeMemberMethod renderMethod = builder.RenderMethod;
CodeMethodReferenceExpression m = new CodeMethodReferenceExpression ();
m.TargetObject = thisRef;
- m.MethodName = builder.renderMethod.Name;
+ m.MethodName = renderMethod.Name;
CodeDelegateCreateExpression create = new CodeDelegateCreateExpression ();
create.DelegateType = new CodeTypeReference (typeof (RenderMethod));
create.TargetObject = thisRef;
- create.MethodName = builder.renderMethod.Name;
+ create.MethodName = renderMethod.Name;
CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression ();
invoke.Method = new CodeMethodReferenceExpression (ctrlVar, "SetRenderMethodDelegate");
invoke.Parameters.Add (create);
- builder.methodStatements.Add (invoke);
+ builder.MethodStatements.Add (invoke);
}
-
- 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, parser.BaseType, parser.MetaResourceKey);
-#endif
+
+ if ((!isTemplate || builder is RootBuilder) && !String.IsNullOrEmpty (builder.GetAttribute ("meta:resourcekey")))
+ CreateAssignStatementFromAttribute (builder, "meta:resourcekey");
+
+ if (!childrenAsProperties && typeof (Control).IsAssignableFrom (builder.ControlType))
+ builder.Method.Statements.Add (new CodeMethodReturnStatement (ctrlVar));
+
+ builder.ProcessGeneratedCode (CompileUnit, BaseType, DerivedType, builder.Method, builder.DataBindingMethod);
+ }
+
+ protected override void AddStatementsToConstructor (CodeConstructor ctor)
+ {
+ if (masterPageContentPlaceHolders == null || masterPageContentPlaceHolders.Count == 0)
+ return;
+
+ var ilist = new CodeVariableDeclarationStatement ();
+ ilist.Name = "__contentPlaceHolders";
+ ilist.Type = new CodeTypeReference (typeof (IList));
+ ilist.InitExpression = new CodePropertyReferenceExpression (thisRef, "ContentPlaceHolders");
+
+ var ilistRef = new CodeVariableReferenceExpression ("__contentPlaceHolders");
+ CodeStatementCollection statements = ctor.Statements;
+ statements.Add (ilist);
+
+ CodeMethodInvokeExpression mcall;
+ foreach (string id in masterPageContentPlaceHolders) {
+ mcall = new CodeMethodInvokeExpression (ilistRef, "Add");
+ mcall.Parameters.Add (new CodePrimitiveExpression (id.ToLowerInvariant ()));
+ statements.Add (mcall);
+ }
}
protected internal override void CreateMethods ()
CreateFrameworkInitializeMethod ();
}
+ protected override void InitializeType ()
+ {
+ List <string> registeredTagNames = parser.RegisteredTagNames;
+ RootBuilder rb = parser.RootBuilder;
+ if (rb == null || registeredTagNames == null || registeredTagNames.Count == 0)
+ return;
+
+ AspComponent component;
+ foreach (string tagName in registeredTagNames) {
+ component = rb.Foundry.GetComponent (tagName);
+ if (component == null || component.Type == null) // unlikely
+ throw new HttpException ("Custom control '" + tagName + "' cannot be found.");
+ if (!(typeof (UserControl).IsAssignableFrom (component.Type)))
+ throw new ParseException (parser.Location, "Type '" + component.Type.ToString () + "' does not derive from 'System.Web.UI.UserControl'.");
+ AddReferencedAssembly (component.Type.Assembly);
+ }
+ }
+
void CallBaseFrameworkInitialize (CodeMemberMethod method)
{
CodeBaseReferenceExpression baseRef = new CodeBaseReferenceExpression ();
CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (baseRef, "FrameworkInitialize");
method.Statements.Add (invoke);
}
-
+
+ void CallSetStringResourcePointer (CodeMemberMethod method)
+ {
+ CodeFieldReferenceExpression stringResource = GetMainClassFieldReferenceExpression ("__stringResource");
+ method.Statements.Add (
+ new CodeMethodInvokeExpression (
+ thisRef,
+ "SetStringResourcePointer",
+ new CodeExpression[] {stringResource, new CodePrimitiveExpression (0)})
+ );
+ }
+
void CreateFrameworkInitializeMethod ()
{
CodeMemberMethod method = new CodeMemberMethod ();
method.Attributes = MemberAttributes.Family | MemberAttributes.Override;
PrependStatementsToFrameworkInitialize (method);
CallBaseFrameworkInitialize (method);
+ CallSetStringResourcePointer (method);
AppendStatementsToFrameworkInitialize (method);
mainClass.Members.Add (method);
}
}
}
+ protected override void CreateStaticFields ()
+ {
+ base.CreateStaticFields ();
+
+ CodeMemberField fld = new CodeMemberField (typeof (object), "__stringResource");
+ fld.Attributes = MemberAttributes.Private | MemberAttributes.Static;
+ fld.InitExpression = new CodePrimitiveExpression (null);
+ mainClass.Members.Add (fld);
+ }
+
protected void ProcessObjectTag (ObjectTagBuilder tag)
{
string fieldName = CreateFieldForObject (tag.Type, tag.ObjectID);
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);
+ mainClass.Members.Add (prop);
}
+ void CreateContentPlaceHolderTemplateProperty (string backingField, string name)
+ {
+ CodeMemberProperty prop = new CodeMemberProperty ();
+ prop.Type = new CodeTypeReference (typeof (ITemplate));
+ prop.Name = name;
+ prop.Attributes = MemberAttributes.Public;
+
+ var ret = new CodeMethodReturnStatement ();
+ var fldRef = new CodeFieldReferenceExpression (thisRef, backingField);
+ ret.Expression = fldRef;
+ prop.GetStatements.Add (ret);
+ prop.SetStatements.Add (new CodeAssignStatement (fldRef, new CodePropertySetValueReferenceExpression ()));
+
+ prop.CustomAttributes.Add (new CodeAttributeDeclaration ("TemplateContainer", new CodeAttributeArgument [] {
+ new CodeAttributeArgument (new CodeTypeOfExpression (new CodeTypeReference (typeof (MasterPage))))
+ }
+ )
+ );
+
+ var enumValueRef = new CodeFieldReferenceExpression (new CodeTypeReferenceExpression (typeof (TemplateInstance)), "Single");
+ prop.CustomAttributes.Add (new CodeAttributeDeclaration ("TemplateInstanceAttribute", new CodeAttributeArgument [] {
+ new CodeAttributeArgument (enumValueRef)
+ }
+ )
+ );
+
+ mainClass.Members.Add (prop);
+ }
+
void CreateAutoHandlers ()
{
// Create AutoHandlers property
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
-
+ prop.CustomAttributes.Add (attr);
mainClass.Members.Add (prop);
// Add the __autoHandlers field
mainClass.Members.Add (prop);
}
-#if NET_2_0
protected virtual string HandleUrlProperty (string str, MemberInfo member)
{
return str;
}
-#endif
TypeConverter GetConverterForMember (MemberInfo member)
{
- TypeConverterAttribute tca = null;
- object[] attrs;
-
-#if NET_2_0
- 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)
+ TypeDescriptionProvider prov = TypeDescriptor.GetProvider (member.ReflectedType);
+ if (prov == null)
return null;
- string typeName = tca.ConverterTypeName;
- if (typeName == null || typeName.Length == 0)
- return null;
+ ICustomTypeDescriptor desc = prov.GetTypeDescriptor (member.ReflectedType);
+ PropertyDescriptorCollection coll = desc != null ? desc.GetProperties () : null;
- Type t = null;
- try {
- t = HttpApplication.LoadType (typeName);
- } catch (Exception) {
- // ignore
- }
+ if (coll == null || coll.Count == 0)
+ return null;
- if (t == null)
+ PropertyDescriptor pd = coll.Find (member.Name, false);
+ if (pd == null)
return null;
- return (TypeConverter) Activator.CreateInstance (t);
+ return pd.Converter;
}
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
+ return new CodeObjectCreateExpression (type, new CodeExpression[] {inst});
}
bool SafeCanConvertFrom (Type type, TypeConverter cvt)
TypeConverter cvt = GetConverterForMember (member);
if (cvt != null && !SafeCanConvertFrom (typeof (string), cvt))
cvt = null;
-
+
object convertedFromAttr = null;
bool preConverted = false;
if (cvt != null && str != null) {
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)
+ 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);
-
-#if NET_2_0
- object[] urlAttr = member.GetCustomAttributes (typeof (UrlPropertyAttribute), true);
- if (urlAttr.Length != 0)
- str = HandleUrlProperty (str, member);
-#endif
- return CreateNullableExpression (originalType, new CodePrimitiveExpression (str), wasNullable);
- }
- if (type == typeof (bool)) {
+ return CreateNullableExpression (originalType, new CodePrimitiveExpression (str), wasNullable);
+ } else if (type == typeof (bool)) {
if (preConverted)
return CreateNullableExpression (originalType,
new CodePrimitiveExpression ((bool) convertedFromAttr),
return CreateNullableExpression (originalType, new CodePrimitiveExpression (true), wasNullable);
else if (InvariantCompareNoCase (str, "false"))
return CreateNullableExpression (originalType, new CodePrimitiveExpression (false), wasNullable);
-#if NET_2_0
else if (wasNullable && InvariantCompareNoCase(str, "null"))
return new CodePrimitiveExpression (null);
-#endif
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);
return CreateNullableExpression (originalType,
new CodePrimitiveExpression (
Convert.ChangeType (preConverted ? convertedFromAttr : str,
- type, CultureInfo.InvariantCulture)),
+ type, Helpers.InvariantCulture)),
wasNullable);
if (type == typeof (string [])) {
}
}
- TypeConverter converter = preConverted ? cvt :
- wasNullable ? TypeDescriptor.GetConverter (type) :
- TypeDescriptor.GetProperties (member.DeclaringType) [member.Name].Converter;
+ 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 (wasNullable)
return CreateNullableExpression (originalType, GenerateInstance (idesc, true),
wasNullable);
-
- return new CodeCastExpression (type, GenerateInstance (idesc, true));
+
+ CodeExpression instance = GenerateInstance (idesc, true);
+ if (type.IsPublic)
+ return new CodeCastExpression (type, instance);
+ else
+ return instance;
}
CodeExpression exp = GenerateObjectInstance (value, false);
if (wasNullable)
return CreateNullableExpression (originalType, invoke, wasNullable);
-
+
return new CodeCastExpression (type, invoke);
}
{
if (value is System.Web.UI.WebControls.Unit) {
System.Web.UI.WebControls.Unit s = (System.Web.UI.WebControls.Unit) value;
+ if (s.IsEmpty) {
+ FieldInfo f = typeof (Unit).GetField ("Empty");
+ return new InstanceDescriptor (f, null);
+ }
ConstructorInfo c = typeof(System.Web.UI.WebControls.Unit).GetConstructor (
BindingFlags.Instance | BindingFlags.Public,
null,
if (value is System.Web.UI.WebControls.FontUnit) {
System.Web.UI.WebControls.FontUnit s = (System.Web.UI.WebControls.FontUnit) value;
+ if (s.IsEmpty) {
+ FieldInfo f = typeof (FontUnit).GetField ("Empty");
+ return new InstanceDescriptor (f, null);
+ }
Type cParamType = null;
object cParam = null;
}
return null;
}
+
+#if DEBUG
+ CodeMethodInvokeExpression CreateConsoleWriteLineCall (string format, params CodeExpression[] parms)
+ {
+ CodeMethodReferenceExpression cwl = new CodeMethodReferenceExpression (new CodeTypeReferenceExpression (typeof (System.Console)), "WriteLine");
+ CodeMethodInvokeExpression cwlCall = new CodeMethodInvokeExpression (cwl);
+
+ cwlCall.Parameters.Add (new CodePrimitiveExpression (format));
+ if (parms != null && parms.Length > 0)
+ foreach (CodeExpression expr in parms)
+ cwlCall.Parameters.Add (expr);
+
+ return cwlCall;
+ }
+#endif
}
}