【阿不】深入ASP.NET資料繫結(下)—多樣的繫結方式

iDotNetSpace發表於2008-07-16

在這個系列的上篇中介紹了資料繫結語法的原理以及.NET中如何實現單向繫結,中篇我們簡單的介紹了ASP.NET 2.0 中新增的Bind語法配合DataSourceControl來實現資料的自動雙向繫結。這兩部分的內容相對動態抽象並且不常接觸,沒有很好的原始碼支援很難解釋清楚,要想真正弄清它們的內部原理,還需要大家親自動手去反編譯分析動態編譯的程式集。

在瞭解了資料繫結語法的原理後,我還想來談談我中實踐過程中遇到的一些問題以及其它實用的繫結技巧。首先我們就來說說,特殊欄位名的問題。我們知道在資料庫當中,如果表名或欄位名中包含有一些特殊的不能是合法的字元時,都會使用[]將它們引起來,以便他們能夠正常使用。但是在的繫結語句當中,同時可以使用[],但是對於欄位名中包含 "(",")","[","]"這4個字元卻始終執行出錯。假設像我下面這樣來繫結"電壓(V)":

# Eval("電壓(V)")%>

那麼就會得到一個執行時錯誤:

DataBinding:“System.Data.DataRowView”不包含名為“電壓”的屬性。

表明括號是被認為是一個特殊字元,那我們如果給欄位名加上[],如下:

# Eval("[電壓(V)]")%>

此時,我們會得到另一個執行時錯誤:

電壓(V 既不是表 DataTable1 的 DataColumn 也不是 DataRelation。

表明,即使加上[]也無法解決這個特殊欄位名的問題。同時欄位名中如果也存在中括號,也是會出現這樣的問題的。但是這樣的欄位名卻在GridView的自動生成列中能被正常繫結呢?問題會出現在哪裡呢?分析和對比GridView的自動生成列與Eval這樣的繫結語法在最終執行繫結程式碼上的不同,我們可以發現,GridView的自動生成列取值並不是使用DataBinder.Eval這個方法,它內部有自己的取值方式,但是在實現上卻是大同小異的。那究竟是在哪裡出現了問題呢?我們找出DataBinder類的定義:

   1: [AspNetHostingPermission(SecurityAction.LinkDemand, Level=200)]
   2: public sealed class DataBinder
   3: {
   4:     // Fields
   5:     private static readonly char[] expressionPartSeparator = new char[] { '.' };
   6:     private static readonly char[] indexExprEndChars = new char[] { ']', ')' };
   7:     private static readonly char[] indexExprStartChars = new char[] { '[', '(' };
   8:  
   9:     // Methods
  10:     public static object Eval(object container, string expression)
  11:     {
  12:         if (expression == null)
  13:         {
  14:             throw new ArgumentNullException("expression");
  15:         }
  16:         expression = expression.Trim();
  17:         if (expression.Length == 0)
  18:         {
  19:             throw new ArgumentNullException("expression");
  20:         }
  21:         if (container == null)
  22:         {
  23:             return null;
  24:         }
  25:         string[] expressionParts = expression.Split(expressionPartSeparator);
  26:         return Eval(container, expressionParts);
  27:     }
  28:  
  29:     private static object Eval(object container, string[] expressionParts)
  30:     {
  31:         object propertyValue = container;
  32:         for (int i = 0; (i < expressionParts.Length) && (propertyValue != null); i++)
  33:         {
  34:             string propName = expressionParts[i];
  35:             if (propName.IndexOfAny(indexExprStartChars) < 0)
  36:             {
  37:                 propertyValue = GetPropertyValue(propertyValue, propName);
  38:             }
  39:             else
  40:             {
  41:                 propertyValue = GetIndexedPropertyValue(propertyValue, propName);
  42:             }
  43:         }
  44:         return propertyValue;
  45:     }
  46:  
  47:     public static string Eval(object container, string expression, string format)
  48:     {
  49:         object obj2 = Eval(container, expression);
  50:         if ((obj2 == null) || (obj2 == DBNull.Value))
  51:         {
  52:             return string.Empty;
  53:         }
  54:         if (string.IsNullOrEmpty(format))
  55:         {
  56:             return obj2.ToString();
  57:         }
  58:         return string.Format(format, obj2);
  59:     }
  60:  
  61:     public static object GetDataItem(object container)
  62:     {
  63:         bool flag;
  64:         return GetDataItem(container, out flag);
  65:     }
  66:  
  67:     public static object GetDataItem(object container, out bool foundDataItem)
  68:     {
  69:         if (container == null)
  70:         {
  71:             foundDataItem = false;
  72:             return null;
  73:         }
  74:         IDataItemContainer container2 = container as IDataItemContainer;
  75:         if (container2 != null)
  76:         {
  77:             foundDataItem = true;
  78:             return container2.DataItem;
  79:         }
  80:         string name = "DataItem";
  81:         PropertyInfo property = container.GetType().GetProperty(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
  82:         if (property == null)
  83:         {
  84:             foundDataItem = false;
  85:             return null;
  86:         }
  87:         foundDataItem = true;
  88:         return property.GetValue(container, null);
  89:     }
  90:  
  91:     public static object GetIndexedPropertyValue(object container, string expr)
  92:     {
  93:         if (container == null)
  94:         {
  95:             throw new ArgumentNullException("container");
  96:         }
  97:         if (string.IsNullOrEmpty(expr))
  98:         {
  99:             throw new ArgumentNullException("expr");
 100:         }
 101:         object obj2 = null;
 102:         bool flag = false;
 103:         int length = expr.IndexOfAny(indexExprStartChars);
 104:         int num2 = expr.IndexOfAny(indexExprEndChars, length + 1);
 105:         if (((length < 0) || (num2 < 0)) || (num2 == (length + 1)))
 106:         {
 107:             throw new ArgumentException(SR.GetString("DataBinder_Invalid_Indexed_Expr", new object[] { expr }));
 108:         }
 109:         string propName = null;
 110:         object obj3 = null;
 111:         string s = expr.Substring(length + 1, (num2 - length) - 1).Trim();
 112:         if (length != 0)
 113:         {
 114:             propName = expr.Substring(0, length);
 115:         }
 116:         if<
                                                            

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-402162/,如需轉載,請註明出處,否則將追究法律責任。

【阿不】深入ASP.NET資料繫結(下)—多樣的繫結方式
請登入後發表評論 登入
全部評論

相關文章