The Common Interface: xType and xObject
The common-interface xType code looks like the following:
public interface xType
{
xType Clone();
xType NewInstance();
bool IsNull{ get; set;}
void SetNull();
object BizValue{ get;set;}
bool ValueChanged { get;}
void ResetChange();
string ToString(string valIfNull,
string format);
void Parse(string val, string valIfNull);
SqlDbType SqlDbType { get;}
}
The solution can completely overcome the barriers around custom class data access and data binding. It also allows you to easily abstract common functionalities into business object templates.
|
|
Some points to keep in mind:
- The xType interface above is far from complete yet. For example, you can incorporate many operations available in SqlTypes to xType. xType presents lots of desirable traits. xType is an interface with a common set of operations for all subtypes. All subtypes such as xSqlInt32, xSqlBoolean, xSqlString, xSqlDateTime, and xImage will implement this interface.
- All subtypes are strongly typed intrinsically. Though the property BizValue returns the generic type object, the data value is represented internally using a strongly typed variable, so you can safely cast object to specific types only if the data is not null. For convenience, all subtypes have a property called Value to get and set the internal value as strongly typed. xType keeps its SQL type information through a property called SqlDbType. Since you can also deduce its .NET type from its SQL type, you can avoid using reflection to get the type information.
- xType contains some of the most common operations, for example, nullability support, string formatting and parsing, state tracking, cloning, etc. Some essential operations such as equality checking and type conversion are not provided yet, but you can delegate them to the Value or BizValue property.
- You could add another property called Name to xType. Name is related to how a business object names its data. I will not deal with this issue in this article.
SQL has 24 types. Accordingly you need to provide 24 corresponding subtypes in .NET as listed in Table 1.
Table 1. The table lists the SQL types along with their corresponding .NET subtypes.
SQL Server Type |
.NET Framework Type |
xType |
bit | Boolean | xBoolean* |
tinyint | Byte | xTinyInt* |
smallint | Int16 | xInt16 |
int | Int32 | xInt32* |
bigint | Int64 | xInt64* |
real | Single | xSingle |
decimal | Decimal | xDecimal |
float | Double | xDouble |
numeric | Decimal | xNumeric |
smallmoney | Decimal | xSmallMoney |
money | Decimal | xMoney |
smalldatetime | DateTime | xSmallDateTime |
datetime | DateTime | xDateTime* |
timestamp | Byte[] | xTimeStamp |
uniqueidentifier | Guid | xUniqueIdentifier |
binary | Byte[] | xBinary |
image | Byte[] | xImage* |
varbinary | Byte[] | xVarBinary |
char | String | xChar |
nchar | String | xNChar |
varchar | String | xString* |
nvarchar | String | xNString |
text | String | xText |
ntext | String | xNText |
sql_variant | Object | xSqlVariant |
I've implemented the xTypes marked with an asterisk in the sample code in this article. Since lots of SQL types map to the same .NET type, the workload is not as big as it looks.
The xObject common interface looks like:
public interface xObject
{
xType GetValueByName(string realName);
string ResolveRealName(string name);
}
In this article, xObject contains only two functions:
ResolveRealName and
GetValueByName. The
GetValueByName function lets you retrieve the property value through the real name; the returned type is xType. Since the identity of a variable can differ in SQL, a business object, and a Web Form, you can use the
ResolveRealName function to get the real name of the property. I assume that the table column name of the data in the SQL code is the real name. There are many ways to implement function
GetValueByName. In this article I use reflection to implement
GetValueByName for simplicity. I also use a simple naming mechanism: the name of the property in the custom class and the control ID in the Web Form are the real name prefixed with a dash plus some other characters such as
m_. Thus resolving the real name just means removing the prefix. You can also employ the property attributes and external XML configuration file to establish the name mapping, but that technique requires more coding.