Created
August 22, 2014 22:29
-
-
Save ventaur/e9e99e4959356b954784 to your computer and use it in GitHub Desktop.
Small modifications to Headspring Enumeration and HTML conventions to support drop-downs for them
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Linq; | |
using System.Reflection; | |
using FubuCore.Util; | |
namespace My.Core.Domain.Models { | |
[Serializable] | |
[DebuggerDisplay("{DisplayName} - {Value}")] | |
public abstract class Enumeration<TEnumeration> : Enumeration<TEnumeration, int> | |
where TEnumeration : Enumeration<TEnumeration> { | |
protected Enumeration(int value, string displayName) : base(value, displayName) {} | |
public static TEnumeration FromInt32(int value) { | |
return FromValue(value); | |
} | |
public static bool TryFromInt32(int listItemValue, out TEnumeration result) { | |
return TryParse(listItemValue, out result); | |
} | |
} | |
[Serializable] | |
[DebuggerDisplay("{DisplayName} - {Value}")] | |
public abstract class Enumeration<TEnumeration, TValue> : IComparable<TEnumeration>, IEquatable<TEnumeration> | |
where TEnumeration : Enumeration<TEnumeration, TValue> | |
where TValue : IComparable { | |
readonly string _displayName; | |
readonly TValue _value; | |
private static readonly Lazy<TEnumeration[]> _enumerations = new Lazy<TEnumeration[]>(GetEnumerations); | |
protected Enumeration(TValue value, string displayName) { | |
_value = value; | |
_displayName = displayName; | |
} | |
public TValue Value { | |
get { return _value; } | |
} | |
public string DisplayName { | |
get { return _displayName; } | |
} | |
public virtual int CompareTo(TEnumeration other) { | |
return Value.CompareTo(other.Value); | |
} | |
public override sealed string ToString() { | |
return DisplayName; | |
} | |
public static TEnumeration[] GetAll() { | |
return _enumerations.Value; | |
} | |
private static TEnumeration[] GetEnumerations() { | |
Type enumerationType = typeof(TEnumeration); | |
return enumerationType | |
.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly) | |
.Where(info => enumerationType.IsAssignableFrom(info.FieldType)) | |
.Select(info => info.GetValue(null)) | |
.Cast<TEnumeration>() | |
.ToArray(); | |
} | |
public static IEnumerable<string> GetAllDisplayNames() { | |
return GetAll().Select(enumeration => enumeration.DisplayName); | |
} | |
public override bool Equals(object obj) { | |
return Equals(obj as TEnumeration); | |
} | |
public bool Equals(TEnumeration other) { | |
return other != null && Value.Equals(other.Value); | |
} | |
public override int GetHashCode() { | |
return Value.GetHashCode(); | |
} | |
public static bool operator ==(Enumeration<TEnumeration, TValue> left, Enumeration<TEnumeration, TValue> right) { | |
return Equals(left, right); | |
} | |
public static bool operator !=(Enumeration<TEnumeration, TValue> left, Enumeration<TEnumeration, TValue> right) { | |
return !Equals(left, right); | |
} | |
public static TEnumeration FromValue(TValue value) { | |
return Parse(value, "value", item => item.Value.Equals(value)); | |
} | |
public static TEnumeration Parse(string displayName) { | |
return Parse(displayName, "display name", item => item.DisplayName == displayName); | |
} | |
static bool TryParse(Func<TEnumeration, bool> predicate, out TEnumeration result) { | |
result = GetAll().FirstOrDefault(predicate); | |
return result != null; | |
} | |
private static TEnumeration Parse(object value, string description, Func<TEnumeration, bool> predicate) { | |
TEnumeration result; | |
if (!TryParse(predicate, out result)) { | |
string message = string.Format("'{0}' is not a valid {1} in {2}", value, description, typeof(TEnumeration)); | |
throw new ArgumentException(message, "value"); | |
} | |
return result; | |
} | |
public static bool TryParse(TValue value, out TEnumeration result) { | |
return TryParse(e => e.Value.Equals(value), out result); | |
} | |
public static bool TryParse(string displayName, out TEnumeration result) { | |
return TryParse(e => e.DisplayName == displayName, out result); | |
} | |
} | |
public static class EnumerationReflectionHelper { | |
private static readonly Cache<Type, MethodInfo> _parseMethodCache = new Cache<Type, MethodInfo>(GetParseMethod); | |
public static object ParseForType(Type enumerationType, string displayName) { | |
MethodInfo parseMethod = _parseMethodCache[enumerationType]; | |
object value = parseMethod.Invoke(null, new object[] { displayName }); | |
return value; | |
} | |
private static MethodInfo GetParseMethod(Type propertyType) { | |
MethodInfo parseMethod = propertyType.GetMethod( | |
"Parse", | |
BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy, | |
null, | |
new[] { typeof(string) }, | |
null); | |
return parseMethod; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Reflection; | |
using FubuCore; | |
using FubuCore.Reflection; | |
using FubuCore.Util; | |
using FubuMVC.Core.UI.Elements; | |
using HtmlTags; | |
using HtmlTags.Conventions; | |
using My.Core.Domain.Models; | |
using My.Website.Conventions.Attributes; | |
namespace My.Website.Conventions { | |
public class EnumerationDropdownBuilder : IElementBuilderPolicy { | |
public const string DefaultPromptText = "[ Select one ]"; | |
private static readonly Cache<Type, IEnumerable<string>> _displayNamesByType = new Cache<Type, IEnumerable<string>>(GetDisplayNamesForType); | |
public bool Matches(ElementRequest subject) { | |
Type propertyType = subject.Accessor.PropertyType; | |
return propertyType.Closes(typeof(Enumeration<,>)); | |
} | |
public ITagBuilder<ElementRequest> BuilderFor(ElementRequest subject) { | |
return new LambdaTagBuilder<ElementRequest>(request => new SelectTag(tag => BuildOptions(request, tag))); | |
} | |
private static void BuildOptions(ElementRequest request, SelectTag tag) { | |
bool showPrompt = request.Accessor.HasAttribute<PromptAttribute>(); | |
if (showPrompt) { | |
var promptAttribute = request.Accessor.GetAttribute<PromptAttribute>(); | |
tag.Option(promptAttribute.Text ?? DefaultPromptText, string.Empty); | |
} | |
foreach (string displayName in _displayNamesByType[request.Accessor.PropertyType]) { | |
tag.Option(displayName, displayName); | |
} | |
string requestValue = request.StringValue(); | |
tag.SelectByValue(requestValue); | |
} | |
private static IEnumerable<string> GetDisplayNamesForType(Type enumerationType) { | |
var getAllDisplayNamesMethod = enumerationType.GetMethod("GetAllDisplayNames", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); | |
var displayNames = getAllDisplayNamesMethod.Invoke(null, null) as IEnumerable<string> ?? Enumerable.Empty<string>(); | |
return displayNames; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
namespace My.Website.Conventions.Attributes { | |
/// <summary> | |
/// Used to adorn properties that are represented as a drop-down/select list to indicate a prompt option/item should be shown. | |
/// </summary> | |
public class PromptAttribute : Attribute { | |
public string Text { get; set; } | |
public PromptAttribute(string text = null) { | |
Text = text; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using FubuCore; | |
using FubuMVC.Core.UI; | |
using FubuMVC.Core.UI.Elements; | |
using HtmlTags; | |
namespace My.Website.Conventions { | |
public class SiteHtmlConventions : HtmlConventionRegistry { | |
public SiteHtmlConventions() { | |
Editors.BuilderPolicy<EnumerationDropdownBuilder>(); | |
// ... | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment