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