Files
ayanova7/source/bizobjects/AyaLib/GZTW.AyaNova.BLL/ReportDataSetAdapter.cs
2018-06-29 19:47:36 +00:00

377 lines
10 KiB
C#

using System;
using System.Data;
using System.Collections;
using System.ComponentModel;
using System.Reflection;
//using CSLA.Resources;
namespace GZTW.AyaNova.BLL
{
#pragma warning disable 1591
/// <summary>
/// An ReportDataSetAdapter is used to convert data in an object
/// or collection into a ReportDataSet suitable for using with AyaNova reporting
/// methods.
/// </summary>
public class ReportDataSetAdapter
{
ArrayList _columns = new ArrayList();
public struct ColumnInfo
{
internal string name;
internal System.Type type;
public string ColumnName
{
get
{
return name;
}
}
public System.Type ColumnType
{
get { return type; }
}
}
/// <summary>
/// Given a data source
/// returns an arraylist containing
/// ColumnInfo structures
/// for each column found
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public ArrayList GetDataSourceColumns(object source)
{
AutoDiscover(source);
return _columns;
}
/// <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(ReportDataSet ds, object source)
{
string className = source.GetType().Name;
Fill(ds, className, source);
}
/// <summary>
/// Fills the DataSet with data from an object or collection.
/// (internally used by AyaNova for reporting compatibility with DevExpress report designer component)
/// </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(ReportDataSet ds, string tableName, object source)
{
DataTable dt = ds.Tables[tableName];
bool 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)
{
AutoDiscover(source);
DataCopy(dt, source);
}
#region Data Copy
void DataCopy(DataTable dt, object source)
{
if(source == null) return;
if(_columns.Count < 1) return;
if(source is IListSource)
{
DataCopyIList(dt, ((IListSource)source).GetList());
}
else
{
if(source is IList)
{
DataCopyIList(dt, (IList)source);
}
else
{
// they gave us a regular object - create a list
ArrayList col = new ArrayList();
col.Add(source);
DataCopyIList(dt, (IList)col);
}
}
}
void DataCopyIList(DataTable dt, IList ds)
{
// create columns if needed
foreach(ColumnInfo column in _columns)
{
if(!dt.Columns.Contains(column.name))
dt.Columns.Add(column.name,column.type);
}
// load the data into the control
dt.BeginLoadData();
for(int index = 0; index < ds.Count; index++)
{
DataRow dr = dt.NewRow();
foreach(ColumnInfo column in _columns)
{
try
{
dr[column.name] = GetField(ds[index], column.name);
}
catch(Exception ex)
{
dr[column.name] = ex.Message;
}
}
dt.Rows.Add(dr);
}
dt.EndLoadData();
}
#endregion
#region AutoDiscover
void AutoDiscover(object source)
{
object innerSource;
if(source is IListSource)
{
innerSource = ((IListSource)source).GetList();
}
else
{
innerSource = source;
}
_columns.Clear();
if(innerSource is DataView)
{
ScanDataView((DataView)innerSource);
}
else
{
if(innerSource is IList)
{
ScanIList((IList)innerSource);
}
else
{
// they gave us a regular object
ScanObject(innerSource);
}
}
}
void ScanDataView(DataView ds)
{
for(int field = 0; field < ds.Table.Columns.Count; field++)
{
ColumnInfo i=new ColumnInfo();
i.name=ds.Table.Columns[field].ColumnName;
i.type=ds.Table.Columns[field].DataType;
_columns.Add(i);
}
}
void ScanIList(IList ds)
{
if(ds.Count > 0)
{
// retrieve the first item from the list
object obj = ds[0];
if(obj is ValueType && obj.GetType().IsPrimitive)
{
// the value is a primitive value type
ColumnInfo i=new ColumnInfo();
i.name="Value";
i.type=obj.GetType();
_columns.Add(i);
}
else
{
if(obj is string)
{
// the value is a simple string
ColumnInfo i=new ColumnInfo();
i.name="Text";
i.type=typeof(string);
_columns.Add(i);
}
else
{
// we have a complex Structure or object
ScanObject(obj);
}
}
}
}
void ScanObject(object source)
{
Type sourceType = source.GetType();
// retrieve a list of all public properties
PropertyInfo [] props = sourceType.GetProperties();
for(int column = 0; column < props.Length; column++)
if(props[column].CanRead)
{
ColumnInfo i=new ColumnInfo();
i.name=props[column].Name;
if(props[column].PropertyType ==typeof(decimal))
i.type=props[column].PropertyType;
else
i.type=typeof(object);
_columns.Add(i);
}
// retrieve a list of all public fields
FieldInfo [] fields = sourceType.GetFields();
for(int column = 0; column < fields.Length; column++)
{
ColumnInfo i=new ColumnInfo();
i.name=fields[column].Name;
i.type=fields[column].FieldType;
_columns.Add(i);
}
}
#endregion
#region GetField
//case 1346 was string but needs to be object to support images
object GetField(object obj, string fieldName)
{
if(obj is DataRowView)
{
// this is a DataRowView from a DataView
return ((DataRowView)obj)[fieldName].ToString();
}
else
{
if(obj is ValueType && obj.GetType().IsPrimitive)
{
// this is a primitive value type
if(obj == null)
return string.Empty;
else
return obj.ToString();
}
else
{
if(obj is string)
{
// this is a simple string
if(obj == null)
return string.Empty;
else
return obj.ToString();
}
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 System.Data.DataException(
"NoSuchValueExistsException" + fieldName);
}
else
{
// got a field, return its value
return field.GetValue(obj).ToString();
}
}
else
{
// found a property, return its value
//case 1346 image fields can't be returned as string
//so return without conversion to string
Type ttt = prop.PropertyType;
//case 1632
if (ttt.IsEnum)
{
//convert to localized text value
System.Enum en=prop.GetValue(obj, null) as System.Enum;
string s= EnumDescConverter.GetEnumDescription(en);
return s;
}
//case 1346
if (ttt == typeof(byte[]) || ttt == typeof(System.Drawing.Bitmap))
{
return prop.GetValue(obj, null);
}
return prop.GetValue(obj, null).ToString();
}
}
catch(Exception ex)
{
throw new System.Data.DataException(
"ErrorReadingValueException" + fieldName, ex);
}
}
}
}
}
#endregion
}
#pragma warning restore 1591
}