using System; using System.Collections.Generic; using System.Reflection; using System.ComponentModel; using Csla.Properties; namespace Csla.Data { /// /// Map data from a source into a target object /// by copying public property values. /// /// public static class DataMapper { #region Map from IDictionary /// /// Copies values from the source into the /// properties of the target. /// /// A name/value dictionary containing the source values. /// An object with properties to be set from the dictionary. /// /// The key names in the dictionary must match the property names on the target /// object. Target properties may not be readonly or indexed. /// public static void Map(System.Collections.IDictionary source, object target) { Map(source, target, false); } /// /// Copies values from the source into the /// properties of the target. /// /// A name/value dictionary containing the source values. /// An object with properties to be set from the dictionary. /// A list of property names to ignore. /// These properties will not be set on the target object. /// /// The key names in the dictionary must match the property names on the target /// object. Target properties may not be readonly or indexed. /// public static void Map(System.Collections.IDictionary source, object target, params string[] ignoreList) { Map(source, target, false, ignoreList); } /// /// Copies values from the source into the /// properties of the target. /// /// A name/value dictionary containing the source values. /// An object with properties to be set from the dictionary. /// A list of property names to ignore. /// These properties will not be set on the target object. /// If , any exceptions will be supressed. /// /// The key names in the dictionary must match the property names on the target /// object. Target properties may not be readonly or indexed. /// public static void Map( System.Collections.IDictionary source, object target, bool suppressExceptions, params string[] ignoreList) { List ignore = new List(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 /// /// Copies values from the source into the /// properties of the target. /// /// An object containing the source values. /// An object with properties to be set from the dictionary. /// /// 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. /// public static void Map(object source, object target) { Map(source, target, false); } /// /// Copies values from the source into the /// properties of the target. /// /// An object containing the source values. /// An object with properties to be set from the dictionary. /// A list of property names to ignore. /// These properties will not be set on the target object. /// /// 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. /// public static void Map(object source, object target, params string[] ignoreList) { Map(source, target, false, ignoreList); } /// /// Copies values from the source into the /// properties of the target. /// /// An object containing the source values. /// An object with properties to be set from the dictionary. /// A list of property names to ignore. /// These properties will not be set on the target object. /// If , any exceptions will be supressed. /// /// /// 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. /// /// Properties to copy are determined based on the source object. Any properties /// on the source object marked with the equal /// to false are ignored. /// /// public static void Map( object source, object target, bool suppressExceptions, params string[] ignoreList) { List ignore = new List(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 result = new List(); PropertyDescriptorCollection props = TypeDescriptor.GetProperties(sourceType); foreach (PropertyDescriptor item in props) if (item.IsBrowsable) result.Add(sourceType.GetProperty(item.Name)); return result.ToArray(); } #endregion /// /// Sets an object's property with the specified value, /// coercing that value to the appropriate type if possible. /// /// Object containing the property to set. /// Name of the property to set. /// Value to set into the property. 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); } } } } }