用扩展方法来扩展IDataReader接口

  实际应用中,有时我们需要用IDataReader来读取数据,或是填充对象,.c# 3.0的扩展方法可以用来扩展这个接口,以实现更方便的功能.以下有泛型方法,也有具体的方法,代码如下:

    9     /// <summary>
   10     /// Contains extension methods for the IDataReader interface.
   11     /// </summary>
   12     /// <remark>Author : PetterLiu 2009-04-17 22:34  http://wintersun.cnblogs.com </remark>
   13     public static class IDataReaderExtensions
   14     {
   15         /// <summary>
   16         /// Gets the IDataReader value.
   17         /// </summary>
   18         /// <typeparam name="T"></typeparam>
   19         /// <param name="reader">The reader.</param>
   20         /// <param name="fieldName">Name of the field.</param>
   21         /// <example><code>
   22         /// <![CDATA[
   23         ///   IDataReader reader = command.ExecuteReader();
   24         ///  if (reader.Read())
   25         ///  {
   26         ///    DateTime date = reader.GetValue<DateTime>("CreationDate");
   27         ///    Int32? orderId = reader.GetValue<Int32?>("NullableID");
   28         ///  }
   29         /// ]]>
   30         /// </code></example>
   31         /// <returns>The column value within the reader typed as T</returns>
   32         public static T GetValue<T>(this IDataReader reader, String fieldName)
   33         {
   34             if (String.IsNullOrEmpty(fieldName))
   35                 throw new ArgumentNullException("Field Name cannot be null");
   36             if (reader[fieldName] is DBNull)
   37                 return default(T);
   38             return (T)reader[fieldName];
   39         }
   40 
   41         /// <summary>
   42         /// Gets the value or default.
   43         /// </summary>
   44         /// <typeparam name="T"></typeparam>
   45         /// <param name="reader">The reader.</param>
   46         /// <param name="columnName">Name of the column.</param>
   47         /// <returns>The column value within the reader typed as T.</returns>
   48         /// <remark>PetterLiu 2009-04-17 22:34  http://wintersun.cnblogs.com </remark>
   49         /// <example><code>
   50         /// <![CDATA[
   51         /// int? myInt = reader.GetValueOrDefault<int?>("myColumnName");
   52         /// DateTime myDate = reader.GetValueOrDefault<DateTime>("myColumnName");
   53         /// ]]>
   54         /// </code></example>
   55         public static T GetValueOrDefault<T>(this IDataReader reader, string columnName)
   56         {
   57             return GetValueOrDefault<T>(reader, columnName, default(T));
   58         }
   59 
   60         /// <summary>
   61         /// Gets the value or default.
   62         /// </summary>
   63         /// <typeparam name="T"></typeparam>
   64         /// <param name="reader">The reader.</param>
   65         /// <param name="columnName">Name of the column.</param>
   66         /// <param name="defaultValue">The default value.</param>
   67         /// <returns>The column value within the reader typed as T.</returns>
   68         /// <remark>PetterLiu 2009-04-17 22:34  http://wintersun.cnblogs.com </remark>
   69         /// <example><code>
   70         /// <![CDATA[
   71         ///  //Default to true if myColumnName is null
   72         /// bool myBool = reader.GetValueOrDefault<bool>("myColumnName", true);
   73         /// ]]>
   74         /// </code></example>
   75         public static T GetValueOrDefault<T>(this IDataReader reader, string columnName, T defaultValue)
   76         {
   77             T returnValue = defaultValue;
   78             int ordinal;
   79             try
   80             {
   81                 ordinal = reader.GetOrdinal(columnName);
   82             }
   83             catch
   84             {
   85                 throw new Exception(string.Format("Column {0} was not found on IDataReader.", columnName));
   86             }
   87             object columnValue = reader.GetValue(ordinal);
   88             if (!(columnValue is DBNull))
   89             {
   90                 Type returnType = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
   91                 returnValue = (T)Convert.ChangeType(columnValue, returnType);
   92             }
   93             return returnValue;
   94         }
   95 
   96         /// <summary>
   97         /// This method will return the value of the specified columnIndex, cast to
   98         /// the type specified in T.  However, if the value found in the reader is
   99         /// DBNull, this method will return the default value of the type T.
  100         /// </summary>
  101         /// <typeparam name="T">The type to which the value found in the reader should be cast.</typeparam>
  102         /// <param name="reader">The reader in which columnIndex exists.</param>
  103         /// <param name="columnName">The columnIndex to retrieve.</param>
  104         /// <returns>The column value within the reader typed as T.</returns>
  105         public static T GetValueOrDefault<T>(this IDataReader reader, int columnIndex)
  106         {
  107             return reader.GetValueOrDefault<T>(reader.GetName(columnIndex));
  108         }
  109 
  110 
  111         /// <summary>
  112         /// Gets the value.
  113         /// </summary>
  114         /// <typeparam name="T"></typeparam>
  115         /// <param name="reader">The reader.</param>
  116         /// <param name="field">The field.</param>
  117         /// <param name="code">The code.</param>
  118         /// <returns>The column value within the reader typed as T.</returns>
  119         /// <example><code>address.ID = dr.GetValue("ID", i => dr.GetInt32(i));</code></example>
  120         /// <remark>PetterLiu 2009-04-17 22:35  http://wintersun.cnblogs.com </remark>
  121         public static T GetValue<T>(this IDataReader reader, string field, Func<int, T> code)
  122         {
  123             T value = default(T);
  124             int ordinal = reader.GetOrdinal(field);
  125             if (!reader.IsDBNull(ordinal))
  126                 value = code(ordinal);
  127             return (value);
  128         }
  129 
  130         /// <summary>
  131         /// Gets the value or null.
  132         /// </summary>
  133         /// <typeparam name="T"></typeparam>
  134         /// <param name="reader">The reader.</param>
  135         /// <param name="field">The field.</param>
  136         /// <param name="code">The code.</param>
  137         /// <returns>The column value within the reader typed as T.</returns>
  138         /// <remark> PetterLiu 2009-04-17 22:38  http://wintersun.cnblogs.com </remark>
  139         public static T? GetValueOrNull<T>(this IDataReader reader, string field, Func<int, T> code) where T : struct
  140         {
  141             T? value = null;
  142             int ordinal = reader.GetOrdinal(field);
  143             if (!reader.IsDBNull(ordinal))
  144                 value = code(ordinal);
  145             return (value);
  146         }
  147 
  148 
  149         /// <summary>
  150         /// Returns a string if one is present, or null if not
  151         /// </summary>
  152         /// <param name="reader">The IDbReader to read from</param>
  153         /// <param name="index">The index of the column to read from</param>
  154         /// <returns>A string, or null if the column's value is NULL</returns>
  155         public static string GetNullableString(this IDataRecord reader, int index)
  156         {
  157             return reader.IsDBNull(index) ? (string)null : reader.GetString(index);
  158         }
  159 
  160         /// <summary>
  161         /// Returns a bool if one is present, or null if not
  162         /// </summary>
  163         /// <param name="reader">The IDbReader to read from</param>
  164         /// <param name="index">The index of the column to read from</param>
  165         /// <returns>A bool, or null if the column's value is NULL</returns>
  166         public static bool? GetNullableBool(this IDataRecord reader, int index)
  167         {
  168             return reader.IsDBNull(index) ? (bool?)null : reader.GetBoolean(index);
  169         }
  170 
  171         /// <summary>
  172         /// Returns a DateTime if one is present, or null if not
  173         /// </summary>
  174         /// <param name="reader">The IDbReader to read from</param>
  175         /// <param name="index">The index of the column to read from</param>
  176         /// <returns>A DateTime, or null if the column's value is NULL</returns>
  177         public static DateTime? GetNullableDateTime(this IDataRecord reader, int index)
  178         {
  179             return reader.IsDBNull(index) ? (DateTime?)null : reader.GetDateTime(index);
  180         }
  181 
  182         /// <summary>
  183         /// Returns a byte if one is present, or null if not
  184         /// </summary>
  185         /// <param name="reader">The IDbReader to read from</param>
  186         /// <param name="index">The index of the column to read from</param>
  187         /// <returns>A byte, or null if the column's value is NULL</returns>
  188         public static byte? GetNullableByte(this IDataRecord reader, int index)
  189         {
  190             return reader.IsDBNull(index) ? (byte?)null : reader.GetByte(index);
  191         }
  192 
  193         /// <summary>
  194         /// Returns a short if one is present, or null if not
  195         /// </summary>
  196         /// <param name="reader">The IDbReader to read from</param>
  197         /// <param name="index">The index of the column to read from</param>
  198         /// <returns>A short, or null if the column's value is NULL</returns>
  199         public static short? GetNullableInt16(this IDataRecord reader, int index)
  200         {
  201             return reader.IsDBNull(index) ? (short?)null : reader.GetInt16(index);
  202         }
  203 
  204         /// <summary>
  205         /// Returns an int if one is present, or null if not
  206         /// </summary>
  207         /// <param name="reader">The IDbReader to read from</param>
  208         /// <param name="index">The index of the column to read from</param>
  209         /// <returns>An int, or null if the column's value is NULL</returns>
  210         public static int? GetNullableInt32(this IDataRecord reader, int index)
  211         {
  212             return reader.IsDBNull(index) ? (int?)null : reader.GetInt32(index);
  213         }
  214 
  215         /// <summary>
  216         /// Returns a float if one is present, or null if not
  217         /// </summary>
  218         /// <param name="reader">The IDbReader to read from</param>
  219         /// <param name="index">The index of the column to read from</param>
  220         /// <returns>A float, or null if the column's value is NULL</returns>
  221         public static float? GetNullableFloat(this IDataRecord reader, int index)
  222         {
  223             return reader.IsDBNull(index) ? (float?)null : reader.GetFloat(index);
  224         }
  225 
  226         /// <summary>
  227         /// Returns a double if one is present, or null if not
  228         /// </summary>
  229         /// <param name="reader">The IDbReader to read from</param>
  230         /// <param name="index">The index of the column to read from</param>
  231         /// <returns>A double, or null if the column's value is NULL</returns>
  232         public static double? GetNullableDouble(this IDataRecord reader, int index)
  233         {
  234             return reader.IsDBNull(index) ? (double?)null : reader.GetDouble(index);
  235         }
  236 
  237     }

几个测试的方法,以及另一个测试所用的扩展方法:

 12         /// <summary>
   13         /// Tests this instance.
   14         /// </summary>
   15         /// <remark>Author : PetterLiu 2009-04-18  0:07  http://wintersun.cnblogs.com </remark>
   16         public void Test()
   17         {
   18               var x = new Person[]
   19             {
   20                 new Person { Id = 1, Name = "Foo", Age = (int?)null },
   21                 new Person { Id = 2, Name = "Bar", Age = (int?)10 }
   22             };
   23               using (var r = x.ToDataReader())
   24               {
   25                   while (r.Read())
   26                   {
   27                       Console.WriteLine("{0}\t{1}\t{2}", r.GetInt32(0), r.GetString(1), r.GetNullableInt32(2));
   28                       Console.WriteLine("{0}\t{1}\t{2}", r.GetInt32(0), r.GetString(1), r.GetValue<int?>("Age"));
   29                       Console.WriteLine("{0}\t{1}\t{2}", r.GetInt32(0), r.GetString(1), r.GetValue("Age", i => r.GetInt32(i)));
   30                   }
   31               }
   32
   33             Console.Read();
   34         }
   35
   36         private class Person
   37         {
   38             public int Id { get; set; }
   39             public string Name { get; set; }
   40             public int? Age { get; set; }
   41         }

 62     public static class TestExtenstion
   63     {
   64         /// <summary>
   65         /// Returns an implementation of IDataReader based on the public properties of T,given an IEnumerable&lt;T&gt;
   66         /// </summary>
   67         /// <typeparam name="T">A type with properties from which to read</typeparam>
   68         /// <param name="items">A collection of instances of T</param>
   69         /// <returns>An implementation of IDataReader based on the public properties of T</returns>
   70         public static IDataReader ToDataReader<T>(this IEnumerable<T> items)
   71         {
   72             return new DataReader<T>(items);
   73         }
   74
   75
   76         /// <summary>
   77         /// Private implementation of IDataReader for an IEnumerable&lt;T&gt;
   78         /// </summary>
   79         /// <typeparam name="T">A type with properties from which to read</typeparam>
   80         private class DataReader<T> : IDataReader
   81         {
   82             public DataReader(IEnumerable<T> items)
   83             {
   84                 _enumerator = items.GetEnumerator();
   85
   86                 foreach (var prop in typeof(T).GetProperties())
   87                 {
   88                     _properties[prop.Name] = prop;
   89                 }
   90             }
   91
   92             private Dictionary<string, PropertyInfo> _properties
   93                 = new Dictionary<string, PropertyInfo>();
   94             private IEnumerator<T> _enumerator;
   95
   96             #region IDataReader Members
   97
   98             public void Close()
   99             {
  100             }
  101
  102             public int Depth
  103             {
  104                 get { return 0; }
  105             }
  106
  107             public DataTable GetSchemaTable()
  108             {
  109                 throw new NotImplementedException();
  110             }
  111
  112             public bool IsClosed
  113             {
  114                 get { return false; }
  115             }
  116
  117             public bool NextResult()
  118             {
  119                 return false;
  120             }
  121
  122             public bool Read()
  123             {
  124                 return _enumerator.MoveNext();
  125             }
  126
  127             public int RecordsAffected
  128             {
  129                 get { throw new NotImplementedException(); }
  130             }
  131
  132             #endregion
  133
  134             #region IDisposable Members
  135
  136             public void Dispose()
  137             {
  138             }
  139
  140             #endregion
  141
  142             #region IDataRecord Members
  143
  144             public int FieldCount
  145             {
  146                 get { return _properties.Count; }
  147             }
  148
  149             public bool GetBoolean(int i)
  150             {
  151                 return (bool)GetValue(i);
  152             }
  153
  154             public byte GetByte(int i)
  155             {
  156                 return (byte)GetValue(i);
  157             }
  158
  159             public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
  160             {
  161                 throw new NotImplementedException();
  162             }
  163
  164             public char GetChar(int i)
  165             {
  166                 return (char)GetValue(i);
  167             }
  168
  169             public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
  170             {
  171                 throw new NotImplementedException();
  172             }
  173
  174             public IDataReader GetData(int i)
  175             {
  176                 throw new NotImplementedException();
  177             }
  178
  179             public string GetDataTypeName(int i)
  180             {
  181                 var prop = _properties.Values.ToArray()[i];
  182                 return prop.PropertyType.ToString();
  183             }
  184
  185             public DateTime GetDateTime(int i)
  186             {
  187                 return (DateTime)GetValue(i);
  188             }
  189
  190             public decimal GetDecimal(int i)
  191             {
  192                 return (decimal)GetValue(i);
  193             }
  194
  195             public double GetDouble(int i)
  196             {
  197                 return (double)GetValue(i);
  198             }
  199
  200             public Type GetFieldType(int i)
  201             {
  202                 var prop = _properties.Values.ToArray()[i];
  203                 return prop.PropertyType;
  204             }
  205
  206             public float GetFloat(int i)
  207             {
  208                 return (float)GetValue(i);
  209             }
  210
  211             public Guid GetGuid(int i)
  212             {
  213                 return (Guid)GetValue(i);
  214             }
  215
  216             public short GetInt16(int i)
  217             {
  218                 return (short)GetValue(i);
  219             }
  220
  221             public int GetInt32(int i)
  222             {
  223                 return (int)GetValue(i);
  224             }
  225
  226             public long GetInt64(int i)
  227             {
  228                 return (long)GetValue(i);
  229             }
  230
  231             public string GetName(int i)
  232             {
  233                 return _properties.Keys.ToArray()[i];
  234             }
  235
  236             public int GetOrdinal(string name)
  237             {
  238                 return _properties.Keys.ToList().IndexOf(name);
  239             }
  240
  241             public string GetString(int i)
  242             {
  243                 return (string)GetValue(i);
  244             }
  245
  246             public object GetValue(int i)
  247             {
  248                 var prop = _properties.Values.ToArray()[i];
  249                 return prop.GetValue(_enumerator.Current, null);
  250             }
  251
  252             public int GetValues(object[] values)
  253             {
  254                 throw new NotImplementedException();
  255             }
  256
  257             public bool IsDBNull(int i)
  258             {
  259                 var prop = _properties.Values.ToArray()[i];
  260                 var val = prop.GetValue(_enumerator.Current, null);
  261                 return (val == null || val == DBNull.Value);
  262             }
  263
  264             public object this[string name]
  265             {
  266                 get
  267                 {
  268                     return _properties[name].GetValue(_enumerator.Current,
  269                         null);
  270                 }
  271             }
  272
  273             public object this[int i]
  274             {
  275                 get
  276                 {
  277                     var prop = _properties.Values.ToArray()[i];
  278                     return prop.GetValue(_enumerator.Current, null);
  279                 }
  280             }
  281
  282             #endregion
  283         }

Author:  Petter Liu  ---  blog:     http://wintersun.cnblogs.com   
posted on 2009-04-18 15:49  PetterLiu  阅读(2238)  评论(0编辑  收藏  举报