/* * DynamORM - Dynamic Object-Relational Mapping library. * Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ using System; using System.Collections; using System.Collections.Generic; using System.Dynamic; namespace DynamORM { /// Dynamic expando is a simple and temporary class to resolve memory leaks inside ExpandoObject. public class DynamicExpando : DynamicObject, IDictionary, ICollection>, IEnumerable>, IEnumerable { /// Class containing information about last accessed property of dynamic object. public class PropertyAccess { /// Enum describing type of access to object. public enum TypeOfAccess { /// Get member. Get, /// Set member. Set, } /// Gets the type of operation. public TypeOfAccess Operation { get; internal set; } /// Gets the name of property. public string Name { get; internal set; } /// Gets the type from binder. public Type RequestedType { get; internal set; } /// Gets the type of value stored in object. public Type Type { get; internal set; } /// Gets the value stored in object. public object Value { get; internal set; } } private Dictionary _data = new Dictionary(); private PropertyAccess _lastProp = new PropertyAccess(); /// Initializes a new instance of the class. public DynamicExpando() { } /// Gets the last accesses property. /// Description of last accessed property. public PropertyAccess GetLastAccessesProperty() { return _lastProp; } /// Tries to get member value. /// Returns true, if get member was tried, false otherwise. /// The context binder. /// The invocation result. public override bool TryGetMember(GetMemberBinder binder, out object result) { result = _data.TryGetValue(binder.Name); _lastProp.Operation = PropertyAccess.TypeOfAccess.Get; _lastProp.RequestedType = binder.ReturnType; _lastProp.Name = binder.Name; _lastProp.Value = result; _lastProp.Type = result == null ? typeof(void) : result.GetType(); return true; } /// Tries to set member. /// Returns true, if set member was tried, false otherwise. /// The context binder. /// Value which will be set. public override bool TrySetMember(SetMemberBinder binder, object value) { _data[binder.Name] = value; _lastProp.Operation = PropertyAccess.TypeOfAccess.Set; _lastProp.RequestedType = binder.ReturnType; _lastProp.Name = binder.Name; _lastProp.Value = value; _lastProp.Type = value == null ? typeof(void) : value.GetType(); return true; } #region IDictionary implementation bool IDictionary.ContainsKey(string key) { return _data.ContainsKey(key); } void IDictionary.Add(string key, object value) { _data.Add(key, value); } bool IDictionary.Remove(string key) { return _data.Remove(key); } bool IDictionary.TryGetValue(string key, out object value) { return _data.TryGetValue(key, out value); } object IDictionary.this[string index] { get { return _data[index]; } set { _data[index] = value; } } ICollection IDictionary.Keys { get { return _data.Keys; } } ICollection IDictionary.Values { get { return _data.Values; } } #endregion IDictionary implementation #region ICollection implementation void ICollection>.Add(KeyValuePair item) { ((ICollection>)_data).Add(item); } void ICollection>.Clear() { _data.Clear(); } bool ICollection>.Contains(KeyValuePair item) { return ((ICollection>)_data).Contains(item); } void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) { ((ICollection>)_data).CopyTo(array, arrayIndex); } bool ICollection>.Remove(KeyValuePair item) { return ((ICollection>)_data).Remove(item); } int ICollection>.Count { get { return _data.Count; } } bool ICollection>.IsReadOnly { get { return ((ICollection>)_data).IsReadOnly; } } #endregion ICollection implementation #region IEnumerable implementation IEnumerator> IEnumerable>.GetEnumerator() { return _data.GetEnumerator(); } #endregion IEnumerable implementation #region IEnumerable implementation IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_data).GetEnumerator(); } #endregion IEnumerable implementation } }