267 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			267 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections;
 | |
| using System.Collections.Generic;
 | |
| using System.Data;
 | |
| using System.ComponentModel;
 | |
| using System.Reflection;
 | |
| using Csla.Properties;
 | |
| 
 | |
| namespace Csla.Data
 | |
| {
 | |
| 
 | |
|   /// <summary>
 | |
|   /// An ObjectAdapter is used to convert data in an object 
 | |
|   /// or collection into a DataTable.
 | |
|   /// </summary>
 | |
|   public class ObjectAdapter
 | |
|   {
 | |
|     /// <summary>
 | |
|     /// Fills the DataSet with data from an object or collection.
 | |
|     /// </summary>
 | |
|     /// <remarks>
 | |
|     /// The name of the DataTable being filled is will be the class name of
 | |
|     /// the object acting as the data source. The
 | |
|     /// DataTable will be inserted if it doesn't already exist in the DataSet.
 | |
|     /// </remarks>
 | |
|     /// <param name="ds">A reference to the DataSet to be filled.</param>
 | |
|     /// <param name="source">A reference to the object or collection acting as a data source.</param>
 | |
|     public void Fill(DataSet ds, object source)
 | |
|     {
 | |
|       string className = source.GetType().Name;
 | |
|       Fill(ds, className, source);
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Fills the DataSet with data from an object or collection.
 | |
|     /// </summary>
 | |
|     /// <remarks>
 | |
|     /// The name of the DataTable being filled is specified as a parameter. The
 | |
|     /// DataTable will be inserted if it doesn't already exist in the DataSet.
 | |
|     /// </remarks>
 | |
|     /// <param name="ds">A reference to the DataSet to be filled.</param>
 | |
|     /// <param name="tableName"></param>
 | |
|     /// <param name="source">A reference to the object or collection acting as a data source.</param>
 | |
|     public void Fill(DataSet ds, string tableName, object source)
 | |
|     {
 | |
|       DataTable dt;
 | |
|       bool exists;
 | |
| 
 | |
|       dt = ds.Tables[tableName];
 | |
|       exists = (dt != null);
 | |
| 
 | |
|       if (!exists)
 | |
|         dt = new DataTable(tableName);
 | |
| 
 | |
|       Fill(dt, source);
 | |
| 
 | |
|       if (!exists)
 | |
|         ds.Tables.Add(dt);
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Fills a DataTable with data values from an object or collection.
 | |
|     /// </summary>
 | |
|     /// <param name="dt">A reference to the DataTable to be filled.</param>
 | |
|     /// <param name="source">A reference to the object or collection acting as a data source.</param>
 | |
|     public void Fill(DataTable dt, object source)
 | |
|     {
 | |
|       if (source == null)
 | |
|         throw new ArgumentException(Resources.NothingNotValid);
 | |
| 
 | |
|       // get the list of columns from the source
 | |
|       List<string> columns = GetColumns(source);
 | |
|       if (columns.Count < 1) return;
 | |
| 
 | |
|       // create columns in DataTable if needed
 | |
|       foreach (string column in columns)
 | |
|         if (!dt.Columns.Contains(column))
 | |
|           dt.Columns.Add(column);
 | |
| 
 | |
|       // get an IList and copy the data
 | |
|       CopyData(dt, GetIList(source), columns);
 | |
|     }
 | |
| 
 | |
|     #region DataCopyIList
 | |
| 
 | |
|     private IList GetIList(object source)
 | |
|     {
 | |
|       if (source is IListSource)
 | |
|         return ((IListSource)source).GetList();
 | |
|       else if (source is IList)
 | |
|         return source as IList;
 | |
|       else
 | |
|       {
 | |
|         // this is a regular object - create a list
 | |
|         ArrayList col = new ArrayList();
 | |
|         col.Add(source);
 | |
|         return col;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
 | |
|     private void CopyData(
 | |
|       DataTable dt, IList ds, List<string> columns)
 | |
|     {
 | |
|       // load the data into the DataTable
 | |
|       dt.BeginLoadData();
 | |
|       for (int index = 0; index < ds.Count; index++)
 | |
|       {
 | |
|         DataRow dr = dt.NewRow();
 | |
|         foreach (string column in columns)
 | |
|         {
 | |
|           try
 | |
|           {
 | |
|             dr[column] = GetField(ds[index], column);
 | |
|           }
 | |
|           catch (Exception ex)
 | |
|           {
 | |
|             dr[column] = ex.Message;
 | |
|           }
 | |
|         }
 | |
|         dt.Rows.Add(dr);
 | |
|       }
 | |
|       dt.EndLoadData();
 | |
|     }
 | |
| 
 | |
|     #endregion
 | |
| 
 | |
|     #region GetColumns
 | |
| 
 | |
|     private List<string> GetColumns(object source)
 | |
|     {
 | |
|       List<string> result;
 | |
|       // first handle DataSet/DataTable
 | |
|       object innerSource;
 | |
|       IListSource iListSource = source as IListSource;
 | |
|       if (iListSource != null)
 | |
|         innerSource = iListSource.GetList();
 | |
|       else
 | |
|         innerSource = source;
 | |
| 
 | |
|       DataView dataView = innerSource as DataView;
 | |
|       if (dataView != null)
 | |
|         result = ScanDataView(dataView);
 | |
|       else
 | |
|       {
 | |
|         // now handle lists/arrays/collections
 | |
|         IEnumerable iEnumerable = innerSource as IEnumerable;
 | |
|         if (iEnumerable != null)
 | |
|         {
 | |
|           Type childType = Utilities.GetChildItemType(
 | |
|             innerSource.GetType());
 | |
|           result = ScanObject(childType);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|           // the source is a regular object
 | |
|           result = ScanObject(innerSource.GetType());
 | |
|         }
 | |
|       }
 | |
|       return result;
 | |
|     }
 | |
| 
 | |
|     private List<string> ScanDataView(DataView ds)
 | |
|     {
 | |
|       List<string> result = new List<string>();
 | |
|       for (int field = 0; field < ds.Table.Columns.Count; field++)
 | |
|         result.Add(ds.Table.Columns[field].ColumnName);
 | |
|       return result;
 | |
|     }
 | |
| 
 | |
|     private List<string> ScanObject(Type sourceType)
 | |
|     {
 | |
|       List<string> result = new List<string>();
 | |
| 
 | |
|       if (sourceType != null)
 | |
|       {
 | |
|         // retrieve a list of all public properties
 | |
|         PropertyInfo[] props = sourceType.GetProperties();
 | |
|         if (props.Length >= 0)
 | |
|           for (int column = 0; column < props.Length; column++)
 | |
|             if (props[column].CanRead)
 | |
|               result.Add(props[column].Name);
 | |
| 
 | |
|         // retrieve a list of all public fields
 | |
|         FieldInfo[] fields = sourceType.GetFields();
 | |
|         if (fields.Length >= 0)
 | |
|           for (int column = 0; column < fields.Length; column++)
 | |
|             result.Add(fields[column].Name);
 | |
|       }
 | |
|       return result;
 | |
|     }
 | |
| 
 | |
|     #endregion
 | |
| 
 | |
|     #region GetField
 | |
| 
 | |
|     private static string GetField(object obj, string fieldName)
 | |
|     {
 | |
|       string result;
 | |
|       DataRowView dataRowView = obj as DataRowView;
 | |
|       if (dataRowView != null)
 | |
|       {
 | |
|         // this is a DataRowView from a DataView
 | |
|         result = dataRowView[fieldName].ToString();
 | |
|       }
 | |
|       else if (obj is ValueType && obj.GetType().IsPrimitive)
 | |
|       {
 | |
|         // this is a primitive value type
 | |
|         result = obj.ToString();
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         string tmp = obj as string;
 | |
|         if (tmp != null)
 | |
|         {
 | |
|           // this is a simple string
 | |
|           result = (string)obj;
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|           // this is an object or Structure
 | |
|           try
 | |
|           {
 | |
|             Type sourceType = obj.GetType();
 | |
| 
 | |
|             // see if the field is a property
 | |
|             PropertyInfo prop = sourceType.GetProperty(fieldName);
 | |
| 
 | |
|             if ((prop == null) || (!prop.CanRead))
 | |
|             {
 | |
|               // no readable property of that name exists - 
 | |
|               // check for a field
 | |
|               FieldInfo field = sourceType.GetField(fieldName);
 | |
|               if (field == null)
 | |
|               {
 | |
|                 // no field exists either, throw an exception
 | |
|                 throw new DataException(
 | |
|                   Resources.NoSuchValueExistsException +
 | |
|                   " " + fieldName);
 | |
|               }
 | |
|               else
 | |
|               {
 | |
|                 // got a field, return its value
 | |
|                 result = field.GetValue(obj).ToString();
 | |
|               }
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|               // found a property, return its value
 | |
|               result = prop.GetValue(obj, null).ToString();
 | |
|             }
 | |
|           }
 | |
|           catch (Exception ex)
 | |
|           {
 | |
|             throw new DataException(
 | |
|               Resources.ErrorReadingValueException +
 | |
|               " " + fieldName, ex);
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       return result;
 | |
|     }
 | |
| 
 | |
|     #endregion
 | |
| 
 | |
|   }
 | |
| } |