I came across the following entity.
https://gist.github.com/breezhang/8954586
public sealed class ForwardingMetaObject : DynamicMetaObject { private readonly DynamicMetaObject _metaForwardee; public ForwardingMetaObject( Expression expression, BindingRestrictions restrictions, object forwarder, IDynamicMetaObjectProvider forwardee, Func<Expression, Expression> forwardeeGetter ) : base(expression, restrictions, forwarder) {
and so I wrote
using System; using System.CodeDom; using System.Collections.Generic; using System.ComponentModel; using System.Dynamic; using System.Linq.Expressions; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using ReactiveUI; namespace Weingartner.Lens { public class Dyno : DynamicObject { private readonly DynamicNotifyingObject _D; public Dyno(DynamicNotifyingObject d) { _D = d; } public override bool TryGetMember(GetMemberBinder binder, out object result) { bool ret = base.TryGetMember(binder, out result); if (ret == false) { result = _D.GetPropertyValue(binder.Name); if (result != null) { ret = true; } } return ret; } public override bool TrySetMember(SetMemberBinder binder, object value) { bool ret = base.TrySetMember(binder, value); if (ret == false) { _D.SetPropertyValue(binder.Name, value); ret = true; } return ret; } }
And the main object that inherits from ReactiveObject, but we can also add dynamic properties.
with test case
using FluentAssertions; using Xunit; namespace Weingartner.Lens.Spec { public class DynamicNotifyingObjectSpec { class Fixture : DynamicNotifyingObject { public Fixture (): base() { this.AddProperty<string>("A"); this.AddProperty<string>("B"); this.SetPropertyValue("A", "AAA"); this.SetPropertyValue("B", "BBB"); } } [Fact] public void ShouldBeAbleToAddPropertiesLaterOn() { var ff = new Fixture(); ff.AddProperty<string>("newProp"); ff.AddProperty<string>("XXXX"); dynamic f = ff; ff.SetPropertyValue("newProp", "CCC"); ((object)(f.newProp)).Should().Be("CCC"); f.XXXX = "XXXX"; f.newProp = "DDD"; ((object)(f.newProp)).Should().Be("DDD"); ((object)(f.XXXX)).Should().Be("XXXX"); } [Fact] public void ShouldGenerateNotificationOnPropertyChange() { var a = new string []{"A"}; var b = new string []{"B"}; object oa = null; object ob = null; var f = new Fixture(); dynamic fd = f; f.PropertyChanged += (sender, ev) => { dynamic s = sender; oa = sA; ob = sB; }; oa.Should().Be(null); ob.Should().Be(null); fd.A = "A"; oa.Should().Be("A"); ob.Should().Be("BBB"); fd.B = "B"; oa.Should().Be("A"); ob.Should().Be("B"); } } }
source share