using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web.UI; using System.Reflection; using System.ComponentModel; using Bowin.Common.Utility; namespace Bowin.Common { public class FormDataBinder { private static Dictionary controlValueProperties = new Dictionary(); public event EventHandler DataItemBinding; public event EventHandler DataItemBound; public static IEnumerable BuildBindingMappings(Type entityType, Control container, string suffix = "") { Guard.ArgumentNotNullOrEmpty(entityType, "entityType"); Guard.ArgumentNotNullOrEmpty(container, "container"); suffix = suffix??string.Empty; return (from property in DataPropertyAttribute.GetDataProperties(entityType) let control = container.FindControl(string.Format("{1}{0}", suffix, property.Name)) let controlValueProperty = GetControlValueProperty(control) where null != control select new BindingMapping(control, controlValueProperty, property)).ToArray(); } public void BindData(object entity, Control container, string suffix = "") { Guard.ArgumentNotNullOrEmpty(entity, "entity"); Guard.ArgumentNotNullOrEmpty(container, "container"); var bingingMappings = BuildBindingMappings(entity.GetType(), container, suffix); this.BindData(entity, bingingMappings); } public void BindData( object entity,IEnumerable bindingMappings) { Guard.ArgumentNotNullOrEmpty(bindingMappings, "bindingMappings"); Guard.ArgumentNotNullOrEmpty(entity, "entity"); this.OnBindData(bindingMappings, entity); } protected virtual void OnBindData(IEnumerable bindingMappings, object entity) { foreach (var bindingMapping in bindingMappings) { object value = bindingMapping.DataSourceProperty.GetValue(entity, null); if (null != this.DataItemBinding) { this.DataItemBinding(this, new DataBindingEventArgs(bindingMapping, value)); } if (!bindingMapping.AutomaticBind) { continue; } if (!string.IsNullOrEmpty(bindingMapping.FormatString)) { value = Format(value, bindingMapping.FormatString); } value = ChangeType(value, bindingMapping.ControlValueProperty.PropertyType); if (null != value) { bindingMapping.ControlValueProperty.SetValue(bindingMapping.Control, value, null); if (null != this.DataItemBound) { this.DataItemBound(this, new DataBindingEventArgs(bindingMapping, value)); } } } } private static object Format(object value, string formatString) { if (null == value) { return string.Empty; } IFormattable formattable = value as IFormattable; if (null != formattable) { return formattable.ToString(formatString, null); } if (value.GetType().IsGenericType && value.GetType().GetGenericTypeDefinition() == typeof(Nullable<>)) { object underlyingValue = Convert.ChangeType(value, Nullable.GetUnderlyingType(value.GetType())); return Format(underlyingValue, formatString); } return value; } private static PropertyInfo GetControlValueProperty(Control control) { if (null == control) { return null; } Type entityType = control.GetType(); if (controlValueProperties.ContainsKey(entityType)) { return controlValueProperties[entityType]; } lock (typeof(FormDataBinder)) { if (controlValueProperties.ContainsKey(entityType)) { return controlValueProperties[entityType]; } var controlValuePropertyAttribute = (ControlValuePropertyAttribute)entityType.GetCustomAttributes(typeof(ControlValuePropertyAttribute), true)[0]; var property = entityType.GetProperty(controlValuePropertyAttribute.Name); controlValueProperties[entityType] = property; return property; } } private static object ChangeType(object value, Type type) { if (null == value) { if (type == typeof(string)) { return string.Empty; } if (type == typeof(bool)) { return false; } return null; } if (type.IsGenericType) { if (type.GetGenericTypeDefinition() == typeof(Nullable<>)) { return new NullableConverter(type).ConvertTo(value, type); } throw new InvalidCastException(string.Format("Invalid cast from \"{0}\" to \"{1}\".", value.GetType().FullName, type.FullName)); } else { return Convert.ChangeType(value, type); } } } }