Merge branch 'master' of github.com:mono/mono
[mono.git] / mcs / class / System.Web / System.Web.UI / DataBinder.cs
index 8010238e09b47b5b192c0e92b278b1bfeab0037c..822ac4b34639eb37d365995d1842c82c95207f99 100644 (file)
@@ -6,7 +6,7 @@
 //     Gonzalo Paniagua Javier (gonzalo@ximian.com)
 //
 // (C) 2002 Ximian, Inc. (http://www.ximian.com)
-// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2005-2010 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -29,6 +29,7 @@
 //
 
 using System.Collections;
+using System.Collections.Generic;
 using System.ComponentModel;
 using System.Reflection;
 using System.Security.Permissions;
@@ -47,7 +48,7 @@ namespace System.Web.UI {
                        if (result == null)
                                return String.Empty;
 
-                       if (format == null)
+                       if (format == null || format.Length == 0)
                                return result.ToString ();
 
                        return String.Format (format, result);
@@ -55,20 +56,21 @@ namespace System.Web.UI {
                
                public static object Eval (object container, string expression)
                {
-                       if ((expression == null) || (expression.Length == 0))
+                       expression = expression != null ? expression.Trim () : null;
+                       if (expression == null || expression.Length == 0)
                                throw new ArgumentNullException ("expression");
 
                        object current = container;
-
                        while (current != null) {
                                int dot = expression.IndexOf ('.');
                                int size = (dot == -1) ? expression.Length : dot;
                                string prop = expression.Substring (0, size);
+                               
                                if (prop.IndexOf ('[') != -1)
                                        current = GetIndexedPropertyValue (current, prop);
                                else
                                        current = GetPropertyValue (current, prop);
-
+                               
                                if (dot == -1)
                                        break;
                                
@@ -128,7 +130,7 @@ namespace System.Web.UI {
                        string property = null;
                        if (openIdx > 0) {
                                property = expr.Substring (0, openIdx);
-                               if (property != null && property != String.Empty)
+                               if (property != null && property.Length > 0)
                                        container = GetPropertyValue (container, property);
                        }
 
@@ -136,17 +138,20 @@ namespace System.Web.UI {
                                 return null;
 
                        if (container is System.Collections.IList) {
+                               if (is_string)
+                                       throw new ArgumentException (expr + " cannot be indexed with a string.");
                                IList l = (IList) container;
                                return l [intVal];
                        }
 
                        Type t = container.GetType ();
+
                        // MS does not seem to look for any other than "Item"!!!
                        object [] atts = t.GetCustomAttributes (typeof (DefaultMemberAttribute), false);
                        if (atts.Length != 1)
-                               throw new ArgumentException (expr + " indexer not found.");
-
-                       property = ((DefaultMemberAttribute) atts [0]).MemberName;
+                               property = "Item";
+                       else
+                               property = ((DefaultMemberAttribute) atts [0]).MemberName;
 
                        Type [] argTypes = new Type [] { (is_string) ? typeof (string) : typeof (int) };
                        PropertyInfo prop = t.GetProperty (property, argTypes);
@@ -172,7 +177,7 @@ namespace System.Web.UI {
                {
                        if (container == null)
                                throw new ArgumentNullException ("container");
-                       if (propName == null)
+                       if (propName == null || propName.Length == 0)
                                throw new ArgumentNullException ("propName");
 
                        PropertyDescriptor prop = TypeDescriptor.GetProperties (container).Find (propName, true);
@@ -190,7 +195,9 @@ namespace System.Web.UI {
                        return FormatResult (result, format);
                }
 
-               #if NET_2_0
+               [ThreadStatic]
+               static Dictionary<Type, PropertyInfo> dataItemCache;
+       
                public static object GetDataItem (object container, out bool foundDataItem)
                {       
                        foundDataItem = false;
@@ -202,11 +209,21 @@ namespace System.Web.UI {
                                return ((IDataItemContainer)container).DataItem;
                        }
                        
-                       PropertyInfo pi = container.GetType ().GetProperty ("DataItem", BindingFlags.Public | BindingFlags.Instance);
+                       PropertyInfo pi = null;
+                       if (dataItemCache == null)
+                               dataItemCache = new Dictionary<Type, PropertyInfo> ();
+                       
+                       Type type = container.GetType ();
+                       if (!dataItemCache.TryGetValue (type, out pi)) {
+                               pi = type.GetProperty ("DataItem", BindingFlags.Public | BindingFlags.Instance);
+                               dataItemCache [type] = pi;
+                       }
+
                        if (pi == null)
                                return null;
                        
                        foundDataItem = true;
+
                        return pi.GetValue (container, null); 
                } 
                
@@ -216,7 +233,6 @@ namespace System.Web.UI {
                        bool flag;
                        return GetDataItem (container, out flag); 
                }
-               #endif
        }
 }