Skip to content

Instantly share code, notes, and snippets.

@jfromaniello
Created January 3, 2011 12:48
Show Gist options
  • Save jfromaniello/763423 to your computer and use it in GitHub Desktop.
Save jfromaniello/763423 to your computer and use it in GitHub Desktop.
using System.Dynamic;
using System.Linq;
using System.Reflection;
using Microsoft.CSharp.RuntimeBinder;
using NUnit.Framework;
using SharpTestsEx;
namespace SampleMixin
{
public class Foo
{
public string FooProperty { get; set; }
}
public class Bar
{
public string BarProperty { get; set; }
}
[TestFixture]
public class SampleTests
{
[Test]
public void CanGetProperty()
{
var foo = new Foo {FooProperty = "Test"};
var bar = new Bar {BarProperty = "Other"};
dynamic mixin = new Mixin(foo, bar);
Assert.AreEqual("Test", mixin.FooProperty);
Assert.AreEqual("Other", mixin.BarProperty);
}
[Test]
public void CanSetProperty()
{
var foo = new Foo {FooProperty = "Test"};
var bar = new Bar {BarProperty = "Other"};
dynamic mixin = new Mixin(foo, bar);
mixin.FooProperty = "Alll";
foo.FooProperty.Should().Be.EqualTo("Alll");
}
[Test]
public void WhenGettingAPropertyThatDoesNotExistsThenThrowRuntimeBinderException()
{
var foo = new Foo {FooProperty = "Test"};
var bar = new Bar {BarProperty = "Other"};
dynamic mixin = new Mixin(foo, bar);
Assert.Throws<RuntimeBinderException>(() => { dynamic r = mixin.InvalidProperty; });
}
[Test]
public void WhenSettingAPropertyThatDoesNotExistsThenThrowRuntimeBinderException()
{
var foo = new Foo {FooProperty = "Test"};
var bar = new Bar {BarProperty = "Other"};
dynamic mixin = new Mixin(foo, bar);
Assert.Throws<RuntimeBinderException>(() => { mixin.InvalidProperty = "Jjjs"; });
}
}
public class Mixin : DynamicObject
{
private readonly object[] mixeds;
public Mixin(params object[] mixeds)
{
this.mixeds = mixeds;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
PropertyObjectPair pair = GetPropertyObjectPair(binder.Name);
if (pair == null)
{
result = null;
return false;
}
object value = pair.Property.GetValue(pair.Object, null);
result = value;
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
PropertyObjectPair pair = GetPropertyObjectPair(binder.Name);
if (pair == null) return false;
pair.Property.SetValue(pair.Object, value, null);
return true;
}
private PropertyObjectPair GetPropertyObjectPair(string binderName)
{
return mixeds.Select(m => new PropertyObjectPair
{
Property = m.GetType().GetProperty(binderName),
Object = m
})
.FirstOrDefault(p => p.Property != null);
}
#region Nested type: PropertyObjectPair
public class PropertyObjectPair
{
public object Object { get; set; }
public PropertyInfo Property { get; set; }
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment