Created
January 26, 2011 18:37
-
-
Save chrisnicola/797177 to your computer and use it in GitHub Desktop.
Updated dynamic dictionary with support for implicit casting
This file contains 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.Dynamic; | |
using System.Linq.Expressions; | |
using Microsoft.CSharp.RuntimeBinder; | |
namespace Nancy | |
{ | |
public class DynamicDictionary : DynamicObject, IEquatable<DynamicDictionary> | |
{ | |
readonly Dictionary<string, dynamic> dictionary = new Dictionary<string, dynamic>(); | |
public override bool TrySetMember(SetMemberBinder binder, dynamic value) | |
{ | |
this[binder.Name] = value; | |
return true; | |
} | |
public override bool TryGetMember(GetMemberBinder binder, out dynamic result) { return dictionary.TryGetValue(binder.Name, out result); } | |
public override IEnumerable<string> GetDynamicMemberNames() { return dictionary.Keys; } | |
public dynamic this[string name] { get { return dictionary[name]; } set { dictionary[name] = value is DynamicDictionaryValue ? value : new DynamicDictionaryValue(value); } } | |
/// <summary> | |
/// Indicates whether the current <see cref = "DynamicDictionary" /> is equal to another object of the same type. | |
/// </summary> | |
/// <returns><see langword = "true" /> if the current instance is equal to the <paramref name = "other" /> parameter; otherwise, <see langword = "false" />.</returns> | |
/// <param name = "other">An <see cref = "DynamicDictionary" /> instance to compare with this instance.</param> | |
public bool Equals(DynamicDictionary other) | |
{ | |
if (ReferenceEquals(null, other)) | |
return false; | |
return ReferenceEquals(this, other) || Equals(other.dictionary, dictionary); | |
} | |
/// <summary> | |
/// Determines whether the specified <see cref = "System.Object" /> is equal to this instance. | |
/// </summary> | |
/// <param name = "obj">The <see cref = "System.Object" /> to compare with this instance.</param> | |
/// <returns><see langword = "true" /> if the specified <see cref = "System.Object" /> is equal to this instance; otherwise, <see langword = "false" />.</returns> | |
public override bool Equals(dynamic obj) | |
{ | |
if (ReferenceEquals(null, obj)) | |
return false; | |
if (ReferenceEquals(this, obj)) | |
return true; | |
return obj.GetType() == typeof (DynamicDictionary) && Equals((DynamicDictionary) obj); | |
} | |
/// <summary> | |
/// Returns a hash code for this <see cref = "DynamicDictionary" />. | |
/// </summary> | |
/// <returns> A hash code for this <see cref = "DynamicDictionary" />, suitable for use in hashing algorithms and data structures like a hash table.</returns> | |
public override int GetHashCode() { return (dictionary != null ? dictionary.GetHashCode() : 0); } | |
} | |
public class DynamicDictionaryValue : DynamicObject | |
{ | |
readonly dynamic value; | |
public DynamicDictionaryValue(dynamic value) { this.value = value; } | |
public override bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result) | |
{ | |
object resultOfCast; | |
result = null; | |
if (binder.Operation != ExpressionType.Equal) | |
return false; | |
var convert = | |
Binder.Convert(CSharpBinderFlags.None, arg.GetType(), typeof (DynamicDictionaryValue)); | |
if (!TryConvert((ConvertBinder) convert, out resultOfCast)) | |
return false; | |
result = (resultOfCast == null) | |
? Equals(arg, resultOfCast) | |
: resultOfCast.Equals(arg); | |
return true; | |
} | |
public override bool TryConvert(ConvertBinder binder, out dynamic result) | |
{ | |
result = null; | |
if (value == null) | |
return true; | |
var binderType = binder.Type; | |
if (binderType == typeof (String)) | |
{ | |
result = Convert.ToString(value); | |
return true; | |
} | |
if (binderType == typeof (Guid) || binderType == typeof (Guid?)) | |
{ | |
Guid guid; | |
} | |
else if (binderType == typeof (TimeSpan) || binderType == typeof (TimeSpan?)) | |
{ | |
TimeSpan timespan; | |
if (TimeSpan.TryParse(Convert.ToString(value), out timespan)) | |
{ | |
result = timespan; | |
return true; | |
} | |
} | |
else | |
{ | |
if (binderType.IsGenericType && binderType.GetGenericTypeDefinition() == typeof (Nullable<>)) | |
binderType = binderType.GetGenericArguments()[0]; | |
var typeCode = Type.GetTypeCode(binderType); | |
if (typeCode == TypeCode.Object) // something went wrong here | |
return false; | |
result = Convert.ChangeType(value, typeCode); | |
return true; | |
} | |
return base.TryConvert(binder, out result); | |
} | |
public override bool TryUnaryOperation(UnaryOperationBinder binder, out object result) { return base.TryUnaryOperation(binder, out result); } | |
public override string ToString() | |
{ | |
if (value == null) | |
return null; | |
return Convert.ToString(value); | |
} | |
public static implicit operator string(DynamicDictionaryValue d) { return d.ToString(); } | |
public static implicit operator Guid(DynamicDictionaryValue d) | |
{ | |
if (d.value is Guid) return d.value; | |
return Guid.Parse(d.ToString()); | |
} | |
public static implicit operator int(DynamicDictionaryValue d) | |
{ | |
if (d.value.GetType().IsValueType) return (int) d.value; | |
return int.Parse(d.ToString()); | |
} | |
public static implicit operator long(DynamicDictionaryValue d) | |
{ | |
if (d.value.GetType().IsValueType) return (long) d.value; | |
return long.Parse(d.ToString()); | |
} | |
public static implicit operator float(DynamicDictionaryValue d) | |
{ | |
if (d.value.GetType().IsValueType) return (float) d.value; | |
return long.Parse(d.ToString()); | |
} | |
public static implicit operator double(DynamicDictionaryValue d) | |
{ | |
if (d.value.GetType().IsValueType) return (double) d.value; | |
return double.Parse(d.ToString()); | |
} | |
public static implicit operator decimal(DynamicDictionaryValue d) | |
{ | |
if (d.value.GetType().IsValueType) return (decimal) d.value; | |
return decimal.Parse(d.ToString()); | |
} | |
public static implicit operator TimeSpan(DynamicDictionaryValue d) | |
{ | |
if (d.value is TimeSpan) return d.value; | |
return TimeSpan.Parse(d.ToString()); | |
} | |
public static implicit operator DateTime(DynamicDictionaryValue d) | |
{ | |
if (d.value is DateTime) return d.value; | |
return DateTime.Parse(d.ToString()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment