Permalink
Browse files

support populating the model from a UIMap

  • Loading branch information...
1 parent 174c27f commit fc59cfc9c73ffc8cf9c9e62a75cf8d31051c49eb @handcraftsman handcraftsman committed Jul 19, 2011
@@ -55,6 +55,7 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\JetBrains.Annotations\JetBrains.Annotations.dll</HintPath>
</Reference>
+ <Reference Include="Microsoft.CSharp" />
<Reference Include="MvbaCore, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\MvbaCore\MvbaCore.dll</HintPath>
@@ -93,6 +94,7 @@
<Compile Include="Extensions\SpanDataExtensions.cs" />
<Compile Include="Extensions\TableDataExtensions.cs" />
<Compile Include="HtmlList.cs" />
+ <Compile Include="IConvertibleExtensions.cs" />
<Compile Include="IHtmlColumn.cs" />
<Compile Include="IListItem.cs" />
<Compile Include="Interfaces\PagedList.cs" />
@@ -102,6 +104,7 @@
<Compile Include="Mapping\IBooleanMap.cs" />
<Compile Include="Mapping\IFreeTextMap.cs" />
<Compile Include="Mapping\IListUIMap.cs" />
+ <Compile Include="Mapping\IModelMap.cs" />
<Compile Include="Mapping\IUIMap.cs" />
<Compile Include="Mapping\ListUIMapWithItem.cs" />
<Compile Include="Mapping\UIMap.cs" />
@@ -0,0 +1,25 @@
+using System;
+
+namespace FluentWebControls
+{
+ public static class IConvertibleExtensions
+ {
+ public static object To(this IConvertible obj, Type targetType)
+ {
+ // based on: http://stackoverflow.com/questions/793714/how-can-i-fix-this-up-to-do-generic-conversion-to-nullablet
+ var underlyingType = Nullable.GetUnderlyingType(targetType);
+
+ if (underlyingType != null)
+ {
+ if (obj == null)
+ return null;
+
+ return Convert.ChangeType(obj, underlyingType);
+ }
+ else
+ {
+ return Convert.ChangeType(obj, targetType);
+ }
+ }
+ }
+}
@@ -17,5 +17,10 @@ string IFreeTextMap.Value
get { return IsChecked.ToString(); }
}
public IPropertyMetaData Validation { get; set; }
+
+ object IModelMap.GetValueForModel()
+ {
+ return IsChecked;
+ }
}
}
@@ -75,5 +75,10 @@ string IFreeTextMap.Value
Validation = Configuration.ValidationMetaDataFactory.GetFor(getProperty);
return this;
}
+
+ object IModelMap.GetValueForModel()
+ {
+ return SelectedValue;
+ }
}
}
@@ -23,20 +23,18 @@ public FreeTextMap(TDomain item, string id, Func<TDomain, string> getValue)
public string Value
{
- get
- {
- if (_value == null)
- {
- _value = _getValue(_item);
- }
- return _value;
- }
+ get { return _value ?? (_value = _getValue(_item)); }
}
public FreeTextMap<TDomain> WithValidation(Expression<Func<TDomain, object>> getProperty)
{
Validation = Configuration.ValidationMetaDataFactory.GetFor(getProperty);
return this;
}
+
+ object IModelMap.GetValueForModel()
+ {
+ return Value;
+ }
}
}
@@ -1,6 +1,6 @@
namespace FluentWebControls.Mapping
{
- public interface IBooleanMap
+ public interface IBooleanMap : IModelMap
{
string Id { get; set; }
bool IsChecked { get; set; }
@@ -4,7 +4,7 @@
namespace FluentWebControls.Mapping
{
- public interface IChoiceListMap
+ public interface IChoiceListMap : IModelMap
{
string Id { get; }
IEnumerable<KeyValuePair<string, string>> ListItems { get; }
@@ -2,7 +2,7 @@
namespace FluentWebControls.Mapping
{
- public interface IFreeTextMap
+ public interface IFreeTextMap : IModelMap
{
string Id { get; }
IPropertyMetaData Validation { get; set; }
@@ -1,3 +1,5 @@
+using System.Dynamic;
+
namespace FluentWebControls.Mapping
{
public interface IListUIMap
@@ -0,0 +1,7 @@
+namespace FluentWebControls.Mapping
+{
+ public interface IModelMap
+ {
+ object GetValueForModel();
+ }
+}
@@ -1,21 +1,25 @@
using System;
using System.Collections.Generic;
-using System.Linq;
+using System.Dynamic;
using System.Linq.Expressions;
using MvbaCore;
namespace FluentWebControls.Mapping
{
public class ListUIMap<TDomain, TModel> : IListUIMap
{
- private readonly Dictionary<string, UIColumn<TDomain>> _columns;
+ private readonly IDictionary<string, object> _columns;
+ private readonly dynamic _container = new ExpandoObject();
public ListUIMap(IEnumerable<TDomain> items)
{
ListItems = items;
- _columns = Reflection
- .GetMatchingProperties(typeof (TDomain), typeof (TModel))
- .ToDictionary(x => x.Name, x => GetMap(x));
+ _columns = (IDictionary<string, object>)_container;
+ foreach (var matchingProperty in Reflection
+ .GetMatchingProperties(typeof (TDomain), typeof (TModel)))
+ {
+ _columns.Add(matchingProperty.Name, GetMap(matchingProperty));
+ }
}
public string IdPrefix { get; set; }
@@ -58,7 +62,7 @@ public DataColumn<TDomain> DataColumnFor(Expression<Func<TModel, object>> forPro
var column = uiMap.TryCastTo<UIColumn<TDomain>>();
return Fluent.DataColumnFor(column.TextMethod, Reflection.GetPropertyName(forPropertyName));
}
-
+
public DataItem<TDomain> DataItemFor(Expression<Func<TModel, object>> forPropertyName)
{
var uiMap = TryGetRequestedMap(forPropertyName);
@@ -86,7 +90,7 @@ public CommandColumn<TDomain> LinkCommandColumnFor(Func<TDomain, string> getCont
{
return Fluent.LinkCommandColumnFor(getControllerActionHrefForSpecificItem);
}
-
+
public CommandItem<TDomain> LinkCommandItemFor(Func<TDomain, string> getControllerActionHrefForSpecificItem)
{
return Fluent.LinkCommandItemFor(getControllerActionHrefForSpecificItem);
@@ -95,7 +99,7 @@ public CommandItem<TDomain> LinkCommandItemFor(Func<TDomain, string> getControll
private object TryGetRequestedMap(Expression<Func<TModel, object>> source)
{
string key = Reflection.GetPropertyName(source);
- UIColumn<TDomain> uiMap;
+ object uiMap;
if (!_columns.TryGetValue(key, out uiMap))
{
throw new ArgumentException("No mapping defined for '" + key + "'");
@@ -1,26 +1,72 @@
using System;
using System.Collections.Generic;
+using System.Dynamic;
using System.Linq;
using System.Linq.Expressions;
-
using FluentWebControls.Extensions;
-
using MvbaCore;
namespace FluentWebControls.Mapping
{
public class UIMap<TDomain, TModel> : IUIMap
where TDomain : class, new()
{
- private readonly Dictionary<string, object> _mappings;
+ private readonly dynamic _container = new ExpandoObject();
+ private readonly IDictionary<string, object> _mappings;
private string _idPrefix;
protected UIMap(TDomain item)
{
Item = item.ToNonNull();
- _mappings = Reflection
- .GetMatchingProperties(typeof(TDomain), typeof(TModel))
- .ToDictionary(x => x.Name, x => GetMap(x));
+ _mappings = (IDictionary<string, object>) _container;
+ foreach (var matchingProperty in Reflection
+ .GetMatchingProperties(typeof (TDomain), typeof (TModel)))
+ {
+ _mappings.Add(matchingProperty.Name, GetMap(matchingProperty));
+ }
+ }
+
+ public void Populate(TModel model)
+ {
+ var properties = typeof (TModel).GetProperties()
+ .ToDictionary(x=>x.Name, x=>x);
+ foreach(var mapping in _mappings)
+ {
+ if (!properties.ContainsKey(mapping.Key)) continue;
+ var property = properties[mapping.Key];
+ var source = mapping.Value as IModelMap;
+ if (source == null) continue;
+ object valueForModel = source.GetValueForModel();
+ if (valueForModel == null)
+ {
+ continue;
+ }
+ var stringValue = valueForModel.ToString();
+ if (stringValue.Length == 0)
+ {
+ continue;
+ }
+
+ if (source is IChoiceListMap &&
+ property.PropertyType.IsGenericType &&
+ property.PropertyType.GetGenericTypeDefinition() == typeof(List<>))
+ {
+ var itemType = property.PropertyType.GetGenericArguments()[0];
+ var choiceList = source as IChoiceListMap;
+ var items = choiceList.ListItems.Select(x => x.Value.To(itemType)).ToList();
+ var targetList = property.GetValue(model, null);
+ var addMethod = targetList.GetType().GetMethod("Add");
+ foreach(var item in items)
+ {
+ addMethod.Invoke(targetList, new[] {item});
+ }
+ }
+ else
+ {
+ var convertedValue = stringValue.To(property.PropertyType);
+ property.SetValue(model, convertedValue, null);
+ }
+ }
}
public TDomain Item { get; private set; }
@@ -81,10 +127,10 @@ protected BooleanMap ConfigureBoolean(Expression<Func<TModel, object>> forId, Fu
if (_mappings.ContainsKey(propertyName) && listUiMap.Validation == null)
{
object value;
- var exists = _mappings.TryGetValue(propertyName, out value);
+ bool exists = _mappings.TryGetValue(propertyName, out value);
if (exists)
{
- listUiMap.Validation = ((FreeTextMap<TDomain>)value).Validation;
+ listUiMap.Validation = ((FreeTextMap<TDomain>) value).Validation;
}
}
_mappings[propertyName] = listUiMap;
@@ -104,10 +150,10 @@ protected BooleanMap ConfigureBoolean(Expression<Func<TModel, object>> forId, Fu
if (listUiMap.Validation == null)
{
object value;
- var exists = _mappings.TryGetValue(propertyName, out value);
+ bool exists = _mappings.TryGetValue(propertyName, out value);
if (exists)
{
- listUiMap.Validation = ((FreeTextMap<TDomain>)value).Validation;
+ listUiMap.Validation = ((FreeTextMap<TDomain>) value).Validation;
}
}
_mappings[propertyName] = listUiMap;
@@ -126,10 +172,10 @@ protected BooleanMap ConfigureBoolean(Expression<Func<TModel, object>> forId, Fu
if (_mappings.ContainsKey(propertyName) && freeTextUiMap.Validation == null)
{
object value;
- var exists = _mappings.TryGetValue(propertyName, out value);
+ bool exists = _mappings.TryGetValue(propertyName, out value);
if (exists)
{
- freeTextUiMap.Validation = ((FreeTextMap<TDomain>)value).Validation;
+ freeTextUiMap.Validation = ((FreeTextMap<TDomain>) value).Validation;
}
}
_mappings[propertyName] = freeTextUiMap;
@@ -165,9 +211,9 @@ public DropDownListData DropDownListFor(Expression<Func<TModel, object>> source)
private object GetMap(PropertyMappingInfo propertyMappingInfo)
{
var info = propertyMappingInfo;
- if (typeof(bool).IsAssignableFrom(propertyMappingInfo.SourcePropertyType))
+ if (typeof (bool).IsAssignableFrom(propertyMappingInfo.SourcePropertyType))
{
- var booleanMap = new BooleanMap(propertyMappingInfo.Name, (bool)info.GetValueFromSource(Item));
+ var booleanMap = new BooleanMap(propertyMappingInfo.Name, (bool) info.GetValueFromSource(Item));
return booleanMap;
}
@@ -176,7 +222,7 @@ private object GetMap(PropertyMappingInfo propertyMappingInfo)
x =>
{
var source = info.GetValueFromSource(x);
- return source == null ? (string)null : source.ToString();
+ return source == null ? (string) null : source.ToString();
});
TryAddValidation(propertyMappingInfo.Name, freeTextMap);
return freeTextMap;

0 comments on commit fc59cfc

Please sign in to comment.