Login | Register   
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Overcoming the Barriers Around Using Custom Classes in ASP.NET : Page 3

Custom classes and collections are often better choices than using a DataSet or DataTable, because they're truly object oriented, letting developers employ robust OOP programming techniques.


advertisement
Implementing xTypes
Implementating these derived types is fairly self-explanatory. Listing 1 shows two representative implementations: xInt32 and xImage. Note these three things:

  • You must ensure that Value is not null when you access the BizValue or Value properties; otherwise an exception will be thrown.
  • If the internal value is represented using a reference type (with the exception of string), the implementation of state change tracking will only track whether its internal reference has been changed.
  • If an operation does not make sense, either an exception will be thrown or a trivial message will be returned, for example, ToString for xImage will simply return a message.
For simplicity, all derived types inherit from an abstract class, xTypeBase, which provides a partial implementation of xType.

Custom Class Data Access
The most troublesome issues in custom data access come from populating a custom class or a custom class collection with data from a DataReader and building the SqlParameters. xType and xObject let you wrap these functionalities into static functions. The following code snippet depicts how you can reduce the process of populating a custom class or collection from a DataReader into one function call:

public static void FillBizObject( xObject xbo, SqlDataReader dr) { int cnt = dr.FieldCount; for (int kk = 0; kk < cnt; kk++) { string realName = dr.GetName(kk); xbo.GetValueByName(realName).BizValue = dr.GetValue(kk); } } public static xObject[] FillBizObjectCollection( xObject objectType, SqlDataReader dr) { ArrayList arr = new ArrayList(); while(dr.Read()) { xObject xbo = objectType.NewInstance(); FillBizObject(xbo, dr); arr.Add(xbo); } return (xObject[])arr.ToArray(); }

The function below shows how to build the SqlParameters. Note that the parameter names are passed in as a parameter. The purpose of doing so is twofold: improve the code readability and inform the function what kind of custom class properties it is operating on. In later sections I will use this technique to deal with generic two-way data binding and create business object templates:

public static SqlParameter[]BuildSqlInputParameters( xObject xbo, params string[] arrNames) { SqlParameter[] arr = new SqlParameter[ arrNames.Length]; for(int kk=0; kk < arrNames.Length; kk++) { string realName = ResolveRealName( arrNames[kk]); xType xt = xbo.GetValueByName(realName); arr[kk] = new SqlParameter("@" + realName, xt.BizValue); } return arr; }

In these functions, xObject serves as the data container passing data back and forth. This is the pattern called Data Transfer Object (References, [3]). Note that you may have other ways or even better ways to write these functions. Here I only want to illustrate how you can wrap these functionalities into a static function with xType and xObject.

With the two hardest problems resolved, you can write a truly object-oriented, data-access component. You can use these two functions to replace tens of lines of data-access-related code in real applications.

Generic Two-way Data Binding in ASP.NET
The basic functionality of a Web Form is to present the data from the data source for viewing and editing. From the perspective of object-oriented thinking, you can map all or part of the properties in a custom class to a group of Web Form server controls (form fields). Practically, because of nullability checking and string formatting and parsing, the mapping requires lots of coding. ASP.NET 2.0 comes with a declarative approach to bind data to and from different data sources, but this method is only available to some ASP.NET 2.0-specific server controls and cannot fully reflect the mapping between the custom class and the group of Web Form fields. The method I will implement can overcome this restriction and establish mapping between a business object and a group of related server controls in the Web Form through data binding functions below:



static void BindDataFromBizObjectToWeb( xObject obj, params xControls[] arrxControls); static void BindDataFromWebToBizObject( xObject obj, params xControls[] arrxControls); static void BindDataFromBizObjectToWeb( xObject obj, Control container, params string[] arrControlIDs); static void BindDataFromWebToBizObject( xObject obj, Control container, params string[] arrControlIDs);

Implementing this technique requires three steps:

  1. Identify a list of controls where you can bind the data to the properties of a business object. Typically, controls that participate in data binding include Literal, Label, TextBox, RadioButton, CheckBox, DropDownList, RadioButtonList, CheckBoxList, ListBox, HiddenField, etc. You can expand this list according to your needs.
  2. Extend the list of the server controls with a common interface called xControl as shown below. All controls must implement the common interface xControl:

public interface xControl { void BindDataFromBizObjectToControl(xObject xbo); void BindDataFromControlToBizObject(xObject xbo); }

  1. Add the extended properties to the controls. Different controls may have different requirements when participating in data binding. These requirements are reflected through the value of the extended properties. For example, when binding data from a business object to Literal, Label, and TextBox, you may need string formatting. For all controls, if data is null, you should specify the replacement value. You can map the items for list controls such as CheckBoxList, RadioButtonList and ListBox to a single property (single mapping) or to a group of properties of Boolean type (multiple mapping). For single mapping, the Control ID corresponds to the property name of the business object. For multiple mapping, each ListItem's Value will map to a custom class property. If you want to use null instead of some string value when the data is posted back, NullIfValuePostBack can meet your needs, but very few of the controls will need this property. I've summarized all these requirements in Table 2. For purposes of clarification, I simply split the list control into two types of controls: single mapping and multiple mapping. Note that ID or ListItem Value may not be the same as the property name of the business object. A supportive function ResolveRealName will resolve the real name from ID or a ListItem Value.
Table 2. The table shows the properties and default values for each common control type.

FormatString

ReplacementIfNull

Default Value

NullIfValuePostBack

Default Value

Mapping

Property Name

 

LiteralEx

yes

Yes

Empty String

No

Single

ID

LabelEx

yes

Yes

Empty String

No

Single

ID

TextBoxEx

yes

Yes

Empty String

Yes

null

Single

ID

RadioButtonEx

No

Yes

False

No

Single

ID

CheckBoxEx

No

Yes

False

No

Single

ID

HiddenFieldEx

No

Yes

Empty String

No

Single

ID

DropDownListEx

No

Yes

Empty String

Yes

null

Single

ID

SingleRadioButtonList

No

Yes

No

Single

ID

MultiRadioButtonList

No

Yes

False

No

Multiple

ListItem Value

CheckBoxListEx

No

Yes

False

No

Multiple

ID

SingleListBox

 

No

Yes

No

Single

ID

MultiListBox

No

Yes

False

No

Multiple

ListItem Value


After you resolve these thorny issues, implementing xControl becomes a fairly easy job. Listing 2 depicts the sample implementation of xTextBox. Listing 3 gives the implementation for the four data-binding functions. It also demonstrates how important it is to define string conversion functions in xType. In Listing 4 I present a different approach to implement this generic two-way data binding.

A business object template is superior to the code generation template in that code generation results in multiple copies of the code template and thus is hard to maintain and scale.
For example, to use this technique in your application, consider two-way data binding with Repeater. RepeaterItem acts as a control container, and in the Repeater, the data-binding event handler code looks like the following:

BindDataFromBizObjectToWeb((xObject)dataItem, repeaterItem, "txt_FirstName", "txt_LastName", "ddl_StateID", ......);

You can also take advantage of declarative syntax in ASPX code. Any public properties in a control can be assigned value using markup code. The following code illustrates this usage:

<ccl:TextBoxEx id="txt_BirthDate" Runat="Server" FormatString="{0:d}" ReplacementIfNull=""> </ccl:TextBox>



Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap