public void ShouldBeAbleToAddMethodsThatHaveAccessToTheMetaObjectInstanceItself() { var wasMethodCalled = new ManualResetEvent(false); var metaObjectsAccessed = new List <MetaObject>(); // Notice how we can access the metaObject instance as part of the method body Action <MetaObject> methodBody = self => { metaObjectsAccessed.Add(self); wasMethodCalled.Set(); }; var foo = new MetaObject(); foo.AddMethod("DoSomething", methodBody); // Match the type signature Assert.True(foo.LooksLike <ISampleDuckInterface>()); var duck = foo.CreateDuck <ISampleDuckInterface>(); duck.DoSomething(); Assert.True(wasMethodCalled.WaitOne(TimeSpan.FromMilliseconds(100))); Assert.Single(metaObjectsAccessed, metaObject => ReferenceEquals(foo, metaObjectsAccessed.First())); }
public void ShouldBeAbleToCreateDuckTypesFromTheMetaObjectItself() { var wasMethodCalled = new ManualResetEvent(false); var metaObject = new MetaObject(); metaObject.AddMethod <Func <int> >("get_Value", () => { wasMethodCalled.Set(); return(42); }); var duck = metaObject.CreateDuck <ISampleInterfaceWithProperties>(); Assert.Equal(42, duck.Value); Assert.True(wasMethodCalled.WaitOne(TimeSpan.FromMilliseconds(100))); }
public void ShouldBeAbleToDuckTypeToAnInterfaceWithProperties() { var wasGetterCalled = new ManualResetEvent(false); var wasSetterCalled = new ManualResetEvent(false); var valueStack = new ConcurrentStack <int>(); Action <int> setValue = newValue => { Assert.Empty(valueStack); wasSetterCalled.Set(); valueStack.Push(newValue); }; Func <int> getValue = () => { Assert.Single(valueStack); wasGetterCalled.Set(); Assert.True(valueStack.TryPeek(out var result)); return(result); }; var metaObject = new MetaObject(); dynamic foo = metaObject; foo.set_Value = setValue; foo.get_Value = getValue; var duckType = metaObject.CreateDuck <ISampleInterfaceWithProperties>(); var expectedValue = 42; duckType.Value = expectedValue; Assert.Equal(expectedValue, duckType.Value); Assert.True(wasGetterCalled.WaitOne()); Assert.True(wasSetterCalled.WaitOne()); }