231 lines
8.4 KiB
C#
231 lines
8.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using System.ComponentModel;
|
|
using Csla.Properties;
|
|
|
|
namespace Csla.Data
|
|
{
|
|
/// <summary>
|
|
/// Map data from a source into a target object
|
|
/// by copying public property values.
|
|
/// </summary>
|
|
/// <remarks></remarks>
|
|
public static class DataMapper
|
|
{
|
|
|
|
#region Map from IDictionary
|
|
|
|
/// <summary>
|
|
/// Copies values from the source into the
|
|
/// properties of the target.
|
|
/// </summary>
|
|
/// <param name="source">A name/value dictionary containing the source values.</param>
|
|
/// <param name="target">An object with properties to be set from the dictionary.</param>
|
|
/// <remarks>
|
|
/// The key names in the dictionary must match the property names on the target
|
|
/// object. Target properties may not be readonly or indexed.
|
|
/// </remarks>
|
|
public static void Map(System.Collections.IDictionary source, object target)
|
|
{
|
|
Map(source, target, false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copies values from the source into the
|
|
/// properties of the target.
|
|
/// </summary>
|
|
/// <param name="source">A name/value dictionary containing the source values.</param>
|
|
/// <param name="target">An object with properties to be set from the dictionary.</param>
|
|
/// <param name="ignoreList">A list of property names to ignore.
|
|
/// These properties will not be set on the target object.</param>
|
|
/// <remarks>
|
|
/// The key names in the dictionary must match the property names on the target
|
|
/// object. Target properties may not be readonly or indexed.
|
|
/// </remarks>
|
|
public static void Map(System.Collections.IDictionary source, object target, params string[] ignoreList)
|
|
{
|
|
Map(source, target, false, ignoreList);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copies values from the source into the
|
|
/// properties of the target.
|
|
/// </summary>
|
|
/// <param name="source">A name/value dictionary containing the source values.</param>
|
|
/// <param name="target">An object with properties to be set from the dictionary.</param>
|
|
/// <param name="ignoreList">A list of property names to ignore.
|
|
/// These properties will not be set on the target object.</param>
|
|
/// <param name="suppressExceptions">If <see langword="true" />, any exceptions will be supressed.</param>
|
|
/// <remarks>
|
|
/// The key names in the dictionary must match the property names on the target
|
|
/// object. Target properties may not be readonly or indexed.
|
|
/// </remarks>
|
|
public static void Map(
|
|
System.Collections.IDictionary source,
|
|
object target, bool suppressExceptions,
|
|
params string[] ignoreList)
|
|
{
|
|
List<string> ignore = new List<string>(ignoreList);
|
|
foreach (string propertyName in source.Keys)
|
|
{
|
|
if (!ignore.Contains(propertyName))
|
|
{
|
|
try
|
|
{
|
|
SetPropertyValue(target, propertyName, source[propertyName]);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
if (!suppressExceptions)
|
|
throw new ArgumentException(
|
|
String.Format("{0} ({1})",
|
|
Resources.PropertyCopyFailed, propertyName), ex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Map from Object
|
|
|
|
/// <summary>
|
|
/// Copies values from the source into the
|
|
/// properties of the target.
|
|
/// </summary>
|
|
/// <param name="source">An object containing the source values.</param>
|
|
/// <param name="target">An object with properties to be set from the dictionary.</param>
|
|
/// <remarks>
|
|
/// The property names and types of the source object must match the property names and types
|
|
/// on the target object. Source properties may not be indexed.
|
|
/// Target properties may not be readonly or indexed.
|
|
/// </remarks>
|
|
public static void Map(object source, object target)
|
|
{
|
|
Map(source, target, false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copies values from the source into the
|
|
/// properties of the target.
|
|
/// </summary>
|
|
/// <param name="source">An object containing the source values.</param>
|
|
/// <param name="target">An object with properties to be set from the dictionary.</param>
|
|
/// <param name="ignoreList">A list of property names to ignore.
|
|
/// These properties will not be set on the target object.</param>
|
|
/// <remarks>
|
|
/// The property names and types of the source object must match the property names and types
|
|
/// on the target object. Source properties may not be indexed.
|
|
/// Target properties may not be readonly or indexed.
|
|
/// </remarks>
|
|
public static void Map(object source, object target, params string[] ignoreList)
|
|
{
|
|
Map(source, target, false, ignoreList);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copies values from the source into the
|
|
/// properties of the target.
|
|
/// </summary>
|
|
/// <param name="source">An object containing the source values.</param>
|
|
/// <param name="target">An object with properties to be set from the dictionary.</param>
|
|
/// <param name="ignoreList">A list of property names to ignore.
|
|
/// These properties will not be set on the target object.</param>
|
|
/// <param name="suppressExceptions">If <see langword="true" />, any exceptions will be supressed.</param>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// The property names and types of the source object must match the property names and types
|
|
/// on the target object. Source properties may not be indexed.
|
|
/// Target properties may not be readonly or indexed.
|
|
/// </para><para>
|
|
/// Properties to copy are determined based on the source object. Any properties
|
|
/// on the source object marked with the <see cref="BrowsableAttribute"/> equal
|
|
/// to false are ignored.
|
|
/// </para>
|
|
/// </remarks>
|
|
public static void Map(
|
|
object source, object target,
|
|
bool suppressExceptions,
|
|
params string[] ignoreList)
|
|
{
|
|
List<string> ignore = new List<string>(ignoreList);
|
|
PropertyInfo[] sourceProperties =
|
|
GetSourceProperties(source.GetType());
|
|
foreach (PropertyInfo sourceProperty in sourceProperties)
|
|
{
|
|
string propertyName = sourceProperty.Name;
|
|
if (!ignore.Contains(propertyName))
|
|
{
|
|
try
|
|
{
|
|
SetPropertyValue(
|
|
target, propertyName,
|
|
sourceProperty.GetValue(source, null));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
if (!suppressExceptions)
|
|
throw new ArgumentException(
|
|
String.Format("{0} ({1})",
|
|
Resources.PropertyCopyFailed, propertyName), ex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static PropertyInfo[] GetSourceProperties(Type sourceType)
|
|
{
|
|
List<PropertyInfo> result = new List<PropertyInfo>();
|
|
PropertyDescriptorCollection props =
|
|
TypeDescriptor.GetProperties(sourceType);
|
|
foreach (PropertyDescriptor item in props)
|
|
if (item.IsBrowsable)
|
|
result.Add(sourceType.GetProperty(item.Name));
|
|
return result.ToArray();
|
|
}
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Sets an object's property with the specified value,
|
|
/// coercing that value to the appropriate type if possible.
|
|
/// </summary>
|
|
/// <param name="target">Object containing the property to set.</param>
|
|
/// <param name="propertyName">Name of the property to set.</param>
|
|
/// <param name="value">Value to set into the property.</param>
|
|
public static void SetPropertyValue(
|
|
object target, string propertyName, object value)
|
|
{
|
|
PropertyInfo propertyInfo =
|
|
target.GetType().GetProperty(propertyName);
|
|
if (value == null)
|
|
propertyInfo.SetValue(target, value, null);
|
|
else
|
|
{
|
|
Type pType =
|
|
Utilities.GetPropertyType(propertyInfo.PropertyType);
|
|
Type vType =
|
|
Utilities.GetPropertyType(value.GetType());
|
|
if (pType.Equals(vType))
|
|
{
|
|
// types match, just copy value
|
|
propertyInfo.SetValue(target, value, null);
|
|
}
|
|
else
|
|
{
|
|
// types don't match, try to coerce
|
|
if (pType.Equals(typeof(Guid)))
|
|
propertyInfo.SetValue(
|
|
target, new Guid(value.ToString()), null);
|
|
else if (pType.IsEnum && vType.Equals(typeof(string)))
|
|
propertyInfo.SetValue(target, Enum.Parse(pType, value.ToString()), null);
|
|
else
|
|
propertyInfo.SetValue(
|
|
target, Convert.ChangeType(value, pType), null);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|