[TestMethod]
public void Can_Set_Get_Properties()
{
dynamic expandable = new ExpandableObject();
expandable.Properties.Add("foo", "good stuff");
Assert.AreEqual(expandable.foo, expandable.Properties["foo"]);
expandable.bar = "yummy";
Assert.AreEqual(expandable.bar, expandable.Properties["bar"]);
}
[TestMethod()]
public void Expandable_Object_Can_Copy_Properties_From_To()
{
dynamic expandable = new ExpandableObject();
var testObj = new TestObject
{
ID = 1,
Description = "ASDFASDF",
Name = "GGGG",
UnitPrice = 6
};
expandable.CopyPropertiesFrom(testObj, null);
Assert.AreEqual(expandable.Description, testObj.Description);
var testObj2 = new TestObject();
expandable.CopyPropertiesTo(testObj2, null);
Assert.AreEqual(testObj, testObj2);
}
Here is the implementation of ExpandableObject.
public class ExpandableObject : DynamicObject
{
Dictionary<string, object>
_properties = new Dictionary<string, object>();
public Dictionary<string, object> Properties
{
get { return _properties; }
set { _properties = value; }
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
_properties[binder.Name] = value;
return true;
}
public override bool TryGetMember(GetMemberBinder binder,
out object result)
{
return _properties.TryGetValue(binder.Name, out result);
}
public void CopyPropertiesFrom(object source, List<string> ignoreList)
{
ignoreList = ignoreList ?? new List<string>();
foreach (var property in source.GetType().GetProperties().Where(p => p.CanRead))
{
var key = property.Name;
if (!ignoreList.Contains(key))
{
var value = property.GetValue(source, null);
this.Properties[key] = value;
}
}
}
public void CopyPropertiesTo(object destination, List<string> ignoreList)
{
ignoreList = ignoreList ?? new List<string>();
var destProps = destination.GetType().GetProperties().ToList();
this.Properties.Keys.ToList().ForEach(key =>
{
if (!ignoreList.Contains(key))
{
var value = this.Properties[key];
var property = destProps.Where(p => p.CanWrite &&
p.Name == key &&
p.PropertyType == value.GetType()).FirstOrDefault();
if (property != null)
{
property.SetValue(destination, value, null);
}
}
});
}
}
There is no spoon…
Enjoy…