/*
* 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