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