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
|
|
|
|
}
|
|
} |